Ano*_*mer 2 c# events multithreading asynchronous
我正在构建一个可供其他开发人员使用的控件,并且在一些地方我有一些事件,开发人员可以订阅这些事件来执行一些可能很长的操作。
我的目标是让他们可以选择使用异步/等待、多线程、后台工作者等,如果他们选择,但仍然能够在事件调用完成之前完成执行。这是一个伪代码示例(我意识到这不能编译,但希望意图很明确):
我的代码:
public event MyEventHandler MyEvent;
private void InvokeMyEvent()
{
var args = new MyEventArgs();
// Keep the UI responsive until this returns
await MyEvent?.Invoke(this, args);
// Then show the result
MessageBox.Show(args.Result);
}
Run Code Online (Sandbox Code Playgroud)
开发者/订阅者的潜在代码:
// Option 1: The operation is very quick,
// so the dev doesn't mind doing it synchronously
private void myForm_MyEvent(object sender, MyEventArgs e)
{
// Short operation, I'll just do it right here.
string result = DoQuickOperation();
e.Result = result;
}
// Option 2, The operation is long,
// so the dev wants to do it on another thread and keep the UI responsive.
private void myForm_MyEvent(object sender, MyEventArgs e)
{
myForm.ShowProgressPanel();
// Long operation, I want to multithread this!
Task.Run(() =>
{
string result = DoVeryLongOperation();
e.Result = result;
})
.ContinueWith((task) =>
{
myForm.HideProgressPanel();
}
}
Run Code Online (Sandbox Code Playgroud)
有没有标准的方法来实现这一点?我正在查看委托的 BeginInvoke 和 EndInvoke 方法,希望它们会有所帮助,但我并没有真正想出什么。
任何帮助或建议将不胜感激!谢谢!
小智 5
没有标准的方法可以做到这一点。
在这种情况下,我个人的偏好是使用自定义委托类型返回Task. 同步返回的处理程序可以简单地 return Task.CompletedTask,他们不需要为此创建新任务。
public delegate Task MyAsyncEventHandler(object sender, MyEventArgs e);
public event MyAsyncEventHandler MyEvent;
private async Task InvokeMyEvent()
{
var args = new MyEventArgs();
// Keep the UI responsive until this returns
var myEvent = MyEvent;
if (myEvent != null)
await Task.WhenAll(Array.ConvertAll(
myEvent.GetInvocationList(),
e => ((MyAsyncEventHandler)e).Invoke(this, args)));
// Then show the result
MessageBox.Show(args.Result);
}
Run Code Online (Sandbox Code Playgroud)
注意myEvent在局部变量中捕获以避免线程问题,并使用GetInvocationList()来确保等待所有任务。
请注意,在此实现中,如果您有多个事件处理程序,它们会同时被调度,因此可以并行执行。处理程序需要确保它们不会args以线程不安全的方式访问。
根据您的用例,按顺序(await在循环中)执行处理程序可能更合适。