5 .net c# concurrency task-parallel-library
我需要一些有关 TPL 和任务的帮助
以下是我的场景:
我有一些生成任务的事件处理程序。如果一个事件在其上一个任务完成之前被调用,我想在继续之前等待(阻止)它。
我有一个同步方法,当调用该方法时,必须等到任何事件处理程序的任何派生任务完成后才能继续。
public void DoSomething()
{
// Expects any running tasks from OnEvent1(), OnEvent2(), OnEvent3()
// to be completed before proceeding.
}
public void OnEvent1()
{
Task.Factory
.StartNew(()=>{ /*Long running task*/ })
.ContinueWith(task=>{ /* Updates UI */ });
}
public void OnEvent2()
{
Task.Factory
.StartNew(()=>{ /*Long running task*/ })
.ContinueWith(task=>{ /* Updates UI */ });
}
public void OnEvent3()
{
Task.Factory
.StartNew(()=>{ /*Long running task*/ })
.ContinueWith(task=>{ /* Updates UI */ });
}
Run Code Online (Sandbox Code Playgroud)
一个实际的场景是:
OnSyncSettings() => 生成任务。对此的所有后续调用都需要排队。
OnAutoBackup() => 同步方法。在保存之前等待任何其他任务(例如,获取数据/同步设置)完成。
我的问题很简单:我该怎么做?
这种方法是否正确?
每个事件处理程序都会记住它的最后一个 . 调用时,它将等待其列表中的所有任务完成后再继续。
对于同步方法,它需要等待所有任务(来自每个事件处理程序)到
Task _lastEvent1Task;
public void OnEvent1()
{
// Wait for all tasks to complete before proceeding
if (_lastEvent1Task!=null)
_lastEvent1Task.Clear();
// Spawns new task
_lastEvent1Task = Task.Factory.StartNew(()=>{ });
}
public void OnEvent3()
{
// Wait for any running tasks to complete before proceeding
if (_lastEvent1Task != null) _lastEvent1Task.Wait();
if (_lastEvent2Task != null) _lastEvent2Task.Wait();
...
// Proceed
}
Run Code Online (Sandbox Code Playgroud)
谢谢!
[编辑]
当 DoSomething() 正在等待并引发 Event1 时?如果 DoSomething() 正在运行并且引发了一个事件怎么办?
OnEvents()
DoSomething()(调用时)
您描述的方法存在并发问题。例如,在对 进行 null 检查之后_lastEvent1Task,其他一些线程可能会设置_lastEvent1Task为 null,从而导致NullReferenceException.
我假设每个任务都应该同步运行,但有些任务不应该阻塞。实现此目的的最佳方法是使用仅利用单个线程的线程,您可以在此处TaskScheduler找到示例。
var scheduler = new SingleThreadedTaskScheduler();
var taskFactory = new TaskFactory(scheduler);
Run Code Online (Sandbox Code Playgroud)
对于非阻塞方法,您会得到如下所示的结果:
public void NonBlockingMethod()
{
taskFactory
.StartNew(() => { /* Long-running work. */ })
.ContinueWith(t => { /* Update UI. */ });
}
Run Code Online (Sandbox Code Playgroud)
对于您获得的阻止方法:
public void BlockingMethod()
{
taskFactory
.StartNew(() => { /* Do work. */ })
.Wait();
}
Run Code Online (Sandbox Code Playgroud)
当你调度任务时,任务调度器将只使用一个线程来调度它们,保证所有任务同步运行。
| 归档时间: |
|
| 查看次数: |
5334 次 |
| 最近记录: |