Sin*_*atr 4 c# events multithreading asynchronous
这需要先解释一下.有一个工作线程必须引发一些事件:
Task.Run(() =>
{
for(int i = 0; i < 123456789; i++)
{
... // some job
OnSomeEvent(i);
}
});
Run Code Online (Sandbox Code Playgroud)
同步上升事件将阻止作业,直到所有事件处理程序完成:
void OnSomeEvent(int i) => SomeEvent?.Invoke(this, new SomeEventArgs(i));
Run Code Online (Sandbox Code Playgroud)
异步事件上升不会再阻止工作了(耶!)
void OnSomeEvent(int i) => Task.Run(() => SomeEvent?.Invoke(this, new SomeEventArgs(i)));
Run Code Online (Sandbox Code Playgroud)
但现在还有另一个问题:未按正确顺序收到事件:
OnSomeEvent(1);
OnSomeEvent(2);
OnSomeEvent(3);
...
// event handler
SomeEvent += (s, e) => Console.WriteLine(e.I);
// possible output
1
3
2
Run Code Online (Sandbox Code Playgroud)
问题:如何实现以正确顺序发生的异步事件上升?
最近我学会了什么Dispatcher.InvokeAsync 使用队列.看起来我必须做类似的事情.如果我必须这样做:1)它应该是呼叫者的工作还是2)我是否应该同步保持上升事件,接收者必须组织生产者/消费者以防止阻塞工作?或许还有另一种方式?
PS:这与ContinueWhith... 无关..除非存储任务列表是一个合适的解决方案.我关注的是如何实现发射并忘记事件,其中:a)呼叫者未被阻止2)事件以相同的顺序接收.
PPS:我不知道如何让MCVE重现这个问题.它出现在具有大量UI,大量线程等的真实项目中.
您可以使用以下TaskQueue命令将异步操作添加到队列,以便在队列中的上一项完成时启动每个操作:
public class TaskQueue
{
private Task previous = Task.FromResult(false);
private object key = new object();
public Task<T> Enqueue<T>(Func<Task<T>> taskGenerator)
{
lock (key)
{
var next = previous.ContinueWith(t => taskGenerator()).Unwrap();
previous = next;
return next;
}
}
public Task Enqueue(Func<Task> taskGenerator)
{
lock (key)
{
var next = previous.ContinueWith(t => taskGenerator()).Unwrap();
previous = next;
return next;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这允许你写:
private TaskQueue taskQueue = new TaskQueue();
private void OnSomeEvent(int i) =>
taskQueue.Enqueue(() => Task.Run(() => SomeEvent?.Invoke(this, new SomeEventArgs(i))));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1633 次 |
| 最近记录: |