简体   繁体   English

同步方法中的异步调用

[英]Asynchronous call in synchronous method

Here is the simple example: 这是一个简单的例子:

public event EventHandler CookinDone = delegate{};

public void CoockinRequest(){
    var indicator = new ActivityIndicator();
    ActivityIndicator.Show("Oooo coockin' something cool");

    var bw = new BackgroundWorker();    
    bw.DoWork += (sender, e) => CockinService.Cook();
    bw.RunWorkerCompleted += (sender, e) => {
       indicator.Hide();
       CookinDone.Invoke(this,null);
    };

    bw.RunWorkerAsync();
}

Now, everytime I use that method I have to intercept CookinDone event and move on. 现在,每次我使用该方法时,我都必须拦截CookinDone事件并继续前进。

var cook = new Cook();
cook.CookinDone += (sender, e) => MessageBox.Show("Yay, smells good");
cook.CoockinRequest();

But how can I simplify that by making return type of the method as Boolean and return result upon the Cookin completion? 但是如何通过将方法的返回类型设置为布尔值并在Cookin完成时返回结果来简化它?

if (CoockinRequest()) MessageBox.Show('Yay, smells even better');

if I put there something like while (bw.IsBusy) it will screw my ActivityIndicator, freeze the main thread and I feel it would be the lousiest thing to do. 如果我把那些东西放在那里while (bw.IsBusy)它将拧紧我的ActivityIndi​​cator,冻结主线程,我觉得这将是最糟糕的事情。 There are also some Monitor.Wait stuff and some other stuff like TaskFactory , but all that stuff seems to be too complicated to use in simple scenarios. 还有一些Monitor.Wait东西和其他一些东西,如TaskFactory ,但所有这些东西似乎太复杂,无法在简单的场景中使用。

It might be also different in different environments, like some approach is good for WPF apps, some for something else and whatnot, but there should be a general pattern isn't that right? 它可能在不同的环境中也有所不同,例如某些方法对WPF应用程序有用,有些对于其他东西以及诸如此类的东西,但应该有一般模式不对吗?

How do you do that guys? 你是怎么做那些家伙的?

There isn't a direct way to do this in .NET 4. This is actually very much in line with the new async/await functionality coming in the next release of C#. 在.NET 4中没有直接的方法可以做到这一点。这实际上非常符合下一版C#中新的async / await功能。

The Task Parallel Library can be used in .NET 4 to accomplish this today. 可以在.NET 4中使用任务并行库来实现此目的。 You would do this by changing your code to return a Task<bool> , so the caller could wait on it (if required), or subscribe a continuation on the task which would run when this was complete. 您可以通过更改代码以返回Task<bool>来执行此操作,以便调用者可以等待它(如果需要),或者在完成此任务时预订任务的继续

To do this, you'd rewrite the above code like so: 为此,您将重写上面的代码,如下所示:

public Task<bool> CoockinRequestAsync()
{
    var indicator = new ActivityIndicator();
    ActivityIndicator.Show("Oooo coockin' something cool");

    // This assumes Cook() returns bool...
    var task = Task.Factory.StartNew(CockinService.Cook);

    // Handle your removal of the indicator here....
    task.ContinueWith( (t) => 
       {
           indicator.Hide();
       }, TaskScheduler.FromCurrentSynchronizationContext());

    // Return the task so the caller can schedule their own completions
    return task;
}

Then, when you go to use this, you'd write something like: 然后,当你去使用它时,你会写下这样的东西:

private void SomeMethod()
{
    var request = this.CoockinRequestAsync();

    request.ContinueWith( t =>
    {
        // This will run when the request completes... 
        bool result = t.Result;

        // Use result as needed here, ie: update your UI

    }, TaskScheduler.FromCurrentSynchronizationContext());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM