本文介绍了等待某事发生 - 异步或同步模型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个方法 WaitForReaderArrival 如下所示:(一直运行等待读者到达)

 public void WaitForReaderArrival(){做{如果(读者到达()){休息;}System.Threading.Thread.Sleep(1000);} while (ReaderArrived() == false);}

我正在等待读者使用,

 await Task.Run(new Action(WaitForReaderArrival));如果(读者到达()){//提高一个读者到达这里!..//胡说八道}

我的一位同事让我将上面的行改为

 WaitForReaderArrival();如果(读者到达()){//提高一个读者到达这里!..//胡说八道}

问题是:

  1. 我上面采用的异步模型真的没有用吗?为什么她要我将该行更改为正常的同步方法对我来说仍然是一个问题.

  2. 上面什么是等待某事发生然后继续的正确方法?

解决方案

您使用的代码是忙等待循环的略微改进版本,其中正在轮询有限制的东西.如果您没有任何其他方式获得更改通知,您可以将此循环卸载到池线程,就像您已经使用 await Task.Run 所做的那样,或者更好的是,使用 Task.Delay:

公共异步任务WaitForReaderArrivalAsync(){而 (!ReaderArrived()){等待 Task.Delay(1000).ConfigureAwait(false);}}

我的一位同事要我更改上面的行...以上是等待某事发生然后的正确方法继续?

你的同事错了.如果你调用你的原始 WaitForReaderArrival 而没有用 await Task.Run 包装它,或者将上面建议的版本称为 WaitForReaderArrivalAsync().Wait(),您将阻塞 UI 线程.为了保持 UI 线程消息循环的功能,您应该使您的代码 "Async All Way:

//顶级事件处理程序async void Button_Click(object sender, EventArgs e){等待 WaitForReaderArrivalAsync();MessageBox.Show("ReaderArrived!");}

这是正确的调用方式.从概念上讲,它与在计时器事件上检查 ReaderArrived 非常相似,但是 async/await 为您提供了方便的线性伪同步代码流.

注意,有一个流行的反模式,它用 DoEvents 忙于等待以保持 UI 响应,有效地在 UI 线程上创建嵌套消息循环:

public void WaitForReaderArrival(){而 (!ReaderArrived()){Application.DoEvents();System.Threading.Thread.Sleep(100);}}

这样做是错误的:保持您的 UI 响应和Application.DoEvents 的危险.

I have this method WaitForReaderArrival which is like below: (Runs all the time waiting for a reader to arrive)

        public void WaitForReaderArrival()
        {
            do
            {
                if (ReaderArrived())
                {
                    break;
                }

                System.Threading.Thread.Sleep(1000);
            } while (ReaderArrived() == false);
        }

And I am awaiting for the reader to arrive using,

 await Task.Run(new Action(WaitForReaderArrival));
 if (ReaderArrived())
 {
      //Raise an ReaderArrived here!
    ..//blah blah
 }

One of my co-worker asked me to change the above line just to

 WaitForReaderArrival();
 if (ReaderArrived())
 {
    //Raise an ReaderArrived here!
    ..//blah blah
 }

The question is:

  1. Is the asynchronous model that I adopted above is not really useful? Why she asked me to change that line to normal synchronous methodology is still a question to me.

  2. What in the above is the right way to wait for something to happen and then proceed?

解决方案

The code you're using is a slightly improved version of the busy waiting loop, which is polling for something with throttling. If you don't have any other ways of getting notified of the change, you can offload this loop to a pool thread as you're doing already with await Task.Run, or better yet, use Task.Delay:

public async Task WaitForReaderArrivalAsync()
{
    while (!ReaderArrived())
    {
        await Task.Delay(1000).ConfigureAwait(false);
    }
}

Your coworker is wrong. If you call your original WaitForReaderArrival without wrapping it with await Task.Run, or call the version proposed above as WaitForReaderArrivalAsync().Wait(), you will block the UI thread. To keep the UI thread message loop functional, you should make your code "Async All the Way":

// top-level event handler
async void Button_Click(object sender, EventArgs e)
{
    await WaitForReaderArrivalAsync();
    MessageBox.Show("ReaderArrived!");
}

That's the right way of calling it. Conceptually, it is very similar to checking ReaderArrived upon a timer event, but async/await gives you convenient linear pseudo-synchronous code flow.

Note, there is a popular anti-pattern which does busy waiting with DoEvents to keep the UI responsive, effectively creating a nested message loop on the UI thread:

public void WaitForReaderArrival()
{
    while (!ReaderArrived())
    {
        Application.DoEvents();
        System.Threading.Thread.Sleep(100);
    }
}

Doing so is wrong: Keeping your UI Responsive and the Dangers of Application.DoEvents.

这篇关于等待某事发生 - 异步或同步模型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-16 07:08