我的问题是很多的。 因为我看到了。 NET 4.5,我印象非常深刻。 不幸的是我所有的项目都是.NET 4.0,我不会考虑迁移。 所以,我想简化我的代码。
目前,我的大部分代码,通常需要足够的时间定格画面,我做到以下几点:
BackgroundWorker bd = new BackgroundWorker();
bd.DoWork += (a, r) =>
{
r.Result = ProcessMethod(r.Argument);
};
bd.RunWorkerCompleted += (a, r) =>
{
UpdateView(r.Result);
};
bd.RunWorkerAsync(args);
老实说,我已经厌倦了。 这成为一个很大的问题时,有一个逻辑复杂的用户交互。
我想知道,如何简化这个逻辑是什么? (请记住,我有。净4.0)我通过谷歌发现了一些东西,但没有发现任何东西容易实现,适合我的需要。
我想下面这个方案:
var foo = args as Foo;
var result = AsyncHelper.CustomInvoke<Foo>(ProcessMethod, foo);
UpdateView(result);
public static class AsyncHelper
{
public static T CustomInvoke<T>(Func<T, T> func, T param) where T : class
{
T result = null;
DispatcherFrame frame = new DispatcherFrame();
Task.Factory.StartNew(() =>
{
result = func(param);
frame.Continue = false;
});
Dispatcher.PushFrame(frame);
return result;
}
}
我不知道的影响是在操纵调度框架。 但我知道,这将很好地工作,例如,我可以在控件的所有事件使用而不打扰,定格画面。 我对泛型类型,协方差知识,逆变是有限的,也许这段代码可以得到改善。
我想到了用其他东西Task.Factory.StartNew
和Dispatcher.Invoke
,但似乎有趣,简单易用罢了。 谁能给我一些启示?
你应该只使用任务并行库(TPL)。 关键是指定TaskScheduler
当前SynchronizationContext
为您更新UI的任何延续。 例如:
Task.Factory.StartNew(() =>
{
return ProcessMethod(yourArgument);
})
.ContinueWith(antecedent =>
{
UpdateView(antecedent.Result);
},
TaskScheduler.FromCurrentSynchronizationContext());
除了一些例外访问前提的,当处理Result
的财产,这是所有有过它。 通过使用FromCurrentSynchronizationContext()
即来自WPF(即DispatcherSynchronizationContext)环境的SynchronizationContext将被用于执行的延续。 这是与调用Dispatcher.[Begin]Invoke
,但你完全从它抽象出来的。
如果你想获得甚至是“干净”,如果你控制ProcessMethod我真的重写返回一个Task
,让它拥有该如何得到纺达(仍然可以使用StartNew
内部)。 这样,你的抽象从ProcessMethod可能要作出自己的,而是他们只担心链接上的延续,等待结果的异步执行决定调用者。
UPDATE 2013年5月22日
应当指出的是,与.NET 4.5在C#中出现和异步语言支持这一规定的技术已经过时,你可以简单地依靠这些功能使用执行特定任务await Task.Run
,然后执行后,将采取地方在调度线程上再次自动地。 因此,像这样:
MyResultType processingResult = await Task.Run(() =>
{
return ProcessMethod(yourArgument);
});
UpdateView(processingResult);
如何封装,始终是在一个可重用的组件相同的代码? 您可以创建一个可冻结它实现ICommand的,暴露类型DoWorkEventHandler和Result属性的属性。 在ICommand.Executed,它会创建一个BackgroundWorker及导线上的DoWork的代表和完成,使用作为事件处理程序DoWorkEventHandler的价值,并在某种程度上处理完成的,它设置了自己的Result属性在事件返回的结果。
你会配置XAML的部件,使用转换器将DoWorkEventHandler财产上的视图模型的方法(我假设你有一个)进行绑定,并将绑定您查看到组件的结果属性,所以它就会自动的结果时更新做了更改通知。
该方案的优点是:它是可重复使用,而且只用XAML的作品,所以在您的视图模型没有更多的胶水代码只是为了处理BackgroundWorkers。 如果你不需要你的后台进程报告进度,甚至有可能不知道它运行在后台线程,所以你是否要同步或异步调用的方法,你可以在XAML决定。
几个月过去了,但会这样帮助你吗?
使用异步/无等待的.NET Framework 4.5