在同步方法异步调用 [英] 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();
}
现在,每次我用这个方法我要拦截CookinDone事件和移动
Now, everytime I use that method I have to intercept CookinDone event and move on.
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?
if (CoockinRequest()) MessageBox.Show('Yay, smells even better');
如果我把有类似而(bw.IsBusy)
它会搞砸我的ActivityIndicator,冻结主线程,我觉得这是做那么最蹩脚的事情。也有一些 Monitor.Wait
的东西和一些其他的东西,比如 TaskFactory
,但所有的东西似乎太复杂在简单的方案中使用。
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. 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.
这可能是在不同的环境也不同,像一些做法是很好的WPF应用程序,有的为别人和诸如此类的东西,但东西应该有一个一般的模式是不对吧?
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?
你怎么做男人?
推荐答案
没有一个直接的方式在.NET 4这实际上是在与新的异步线路非常要这样做/等待功能在C#中的下一个版本的到来。
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中使用该今天完成。布尔> ,所以调用者可以等待就可以了(如果需要),或认购一个的继续你会改变你的代码返回任务<做到这一点。就当这是完成这将运行任务EM>
The Task Parallel Library can be used in .NET 4 to accomplish this today. 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.
要做到这一点,你会重写上面的代码如下所示:
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());
}
这篇关于在同步方法异步调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!