C#命名任务什么是正确的方法?

时间:2015-09-29 17:18:39

标签: c# multithreading task

我正在努力处理连锁任务。

我的想法是使用与下一个代码类似的东西,但VS将我的代码标记为:

  
    

无法转换为System.Threading.Tasks.Task'到' System.Action'在Argument1

  

这种语法的正确方法是什么?

public void startAllTasks()
{
    Task task1 = new Task(() => GetLocalDbRecords());
    Task task2 = new Task(() => CreatePlainTextFile());
    Task task3 = new Task(() => SendToWS());
    task1.ContinueWith(task2);
    task2.ContinueWith(task3);
    task1.Start();
}

我通过使用下一个代码获得了我想要的结果(我知道我必须优化它),但我的想法是通过使用" ContinueWith"来改进它。和一个CancellationToken,但没有运气

public void startAllTasks()
        {
            records = 0;
            stopFlag = false;
            tasksRunning = new Dictionary<int, bool>();
            tasksRunning.Add(1, false);
            tasksRunning.Add(2, false);
            tasksRunning.Add(3, false);
            currentStep = 0;
            while (!stopFlag)
            {
                if (currentStep == 0 && !tasksRunning[1])
                {
                    tasksRunning[1] = true;
                    Task task1 = new Task(() => this.GetLocalDbRecords());
                    task1.Start();
                }
                if (currentStep == 1 && !tasksRunning[2])
                {
                    tasksRunning[2] = true;
                    Task task2 = new Task(() => this.CreatePlainTextFile());
                    task2.Start();
                }
                if (currentStep == 3 && !tasksRunning[3])
                {
                    tasksRunning[3] = true;
                    Task task3 = new Task(() => this.SendToWS());
                    task3.Start();
                }
                Thread.Sleep(100);
            }
        }

1 个答案:

答案 0 :(得分:2)

这是正确的语法(下面的解释):

Task task1 = new Task(() => GetLocalDbRecords());
Task task2 = new Task(() => CreatePlainTextFile());
Task task3 = new Task(() => SendToWS());
task1.ContinueWith(x => task2.Start());
task2.ContinueWith(x => task3.Start());
task1.Start();

请注意,ContinueWith方法收到Task时未收到Action<Task>,在第一个Action完成后会调用此Task将收到第一个Task作为参数,以便您可以使用它的返回值。

您还可以使用Task.Factory流畅语法,这也消除了您使用Task.Start()的需要:

Task.Factory.StartNew(GetLocalDbRecords)
    .ContinueWith(x => CreatePlainTextFile())
    .ContinueWith(x => SendToWS())
    .Wait();

要使用CancellationToken,您需要使用CancellationTokenSource,它的工作原理如下:

来自MSDN's Page about Task cancellation

  

1)创建并启动可取消的任务。

     

2)将取消令牌传递给您的用户委托,并可选择传递给任务实例。

     

3)注意并回复您的用户代表中的取消请求。

     

4)可选地在调用线程上注意任务被取消。

代码示例:

CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;

Task.Factory.StartNew(GetLocalDbRecords)
    .ContinueWith(x => CreatePlainTextFile(), tokenSource.Token)
    .ContinueWith(x => SendToWS(), tokenSource.Token);

tokenSource.Cancel();
bool cancelationRequested = token.IsCancellationRequested; //Value will be true.
使用Task时,

tokenSource.Cancel();不会自动停止,因为它们可能会在调用它们的同一Thread上运行,并且必须知道CancellationToken和民意调查IsCancellationRequested如果他们希望根据它停止,但是,如果Task或其连续的Task试图在CancellationToken已被请求取消时尝试启动, <{1}}或其连续的Task首先不会被调用。

此外,您可以使用Task在取消前设置超时。