这是一个很简单的例子这是在异步/等待概念互联网上可用
这是一个非常糟糕的例子。
它使用任务构造函数和Start
,这是一个明确的no-no(字面意思是没有有效的用例来做到这一点)。
它还在“异步示例”中的后台线程上同步使用文件系统。
如果你想的如何异步消费同步(例如,CPU绑定)代码的一个例子,那么这是一个更好的例子,几乎做同样的事情:
int countCharacters()
{
Thread.Sleep(5000);
return 13;
}
private async void btnProcessFIle_Click(object sender, EventArgs e)
{
var count = await Task.Run(() => countCharacters());
lblCount.Text = "No. of characters in file=" + count;
}
注意,这是的示例如何异步调用UI线程的CPU绑定代码 - 它是而不是“异步概念”的示例。
我不知道如何使用开始/结束调用来实现这个小逻辑?
由于您的工作是在后台线程上同步工作,这实际上很简单; you can just use Delegate.BeginInvoke
而不是创建自己的IAsyncResult
(这是关于APM的非常困难的部分 - 如果您确实需要实现它,请参阅2007-03 issue of MSDN Magazine中的“实现CLR异步编程模型”)。
但因为你可以只使用Delegate.BeginInvoke
,这是非常简单的:
private void btnProcessFIle_Click(object sender, EventArgs e)
{
var ui = SynchronizationContext.Current;
Func<int> d = countCharacters;
d.BeginInvoke(CountCharactersCallback, ui);
}
private void CountCharactersCallback(IAsyncResult ar)
{
var d = (Func<int>) ((AsyncResult) ar).AsyncDelegate;
var ui = (SynchronizationContext) ar.AsyncState;
try
{
var count = d.EndInvoke(ar);
ui.Post(CountCharactersComplete, count);
}
catch (Exception ex)
{
var edi = ExceptionDispatchInfo.Capture(ex);
ui.Post(CountCharactersError, state);
}
}
private void CountCharactersComplete(object state)
{
var count = (int) state;
lblCount.Text = "No. of characters in file=" + count;
}
private void CountCharactersError(object state)
{
var edi = (ExceptionDispatchInfo)state;
edi.Throw();
}
注:
CountCharactersCallback
是 “裸露的回调”。从CountCharactersCallback
传播的任何例外都表示灾难性错误。
- 尤其要注意的是,不要允许
EndInvoke
的例外传播出BeginInvoke
回调。这是一个常见的错误。
- 我使用
SynchronizationContext
来同步回UI线程。这与await
的行为相同。
- 我使用
ExceptionDispatchInfo
跨线程保留异常堆栈跟踪(不需要包装异常)。
CountCharactersError
只是直接在消息循环中引发异常。这与async void
的行为相同。
我很好奇。为什么你想要完美的异步/等待代码并将其转换为使用Begin/End Invoke?开始/结束调用是做它的老方法。一旦你开始使用async/await,除了提交你需要做的家庭作业外,没有任何理由。 – bradgonesurfing
你有什么尝试?你有什么特别的问题?从字面上看,使用_only_'Begin/EndInvoke()'是无法做到你想要的,因为它们没有包含'await'功能,它可以让你在完成时返回正确的线程。你需要添加一个对'Control.Invoke()'的调用来完成它,或者使用'Progress',或者使用'SynchronizationContext',或者......正如你所看到的那样,你的问题太广泛了,除了不包含一个好的[mcve]帮助我们理解你实际需要帮助的是什么。 –
@PeterDuniho我知道的是: 当我在async方法中调用这个KW的任何方法时,Await是一个暂停点,该函数将在后台运行。所有我想要使用痛苦的结构映射相同的逻辑Begin/EndInvoke。 由于Delegates是异步编程的传统方式,而Async/Await自4.5版以来一直与我们在一起。 –