C#任务控制流逻辑无法正常运行

时间:2016-05-31 14:40:05

标签: c# winforms

我有一个Windows窗体应用程序,其中包含一个触发以下操作的按钮:

private async void timeStampDocuments_Click(object sender, System.EventArgs e)
{
    await PerformTask(TimeStampPdfs());
}

PerformTask方法如下:

private async System.Threading.Tasks.Task PerformTask(System.Threading.Tasks.Task task)
{
    if(documentsView.CheckedItems.Count > 0)
    {
        Enabled = false;
        try
        {
            await task;
        }
        catch(System.Exception e)
        {
            System.Windows.Forms.MessageBox.Show("Exception: " + e.Message);
        }
        progressBar.Value = 0;
        progressBar.Text = string.Empty;
        Enabled = true;
    }
    else
    {
        System.Windows.Forms.MessageBox.Show("Please select at least one document.");
    }
}

问题是即使条件为假(documentsView.CheckedItemsCount等于0),任务仍然执行。但是,一旦任务完成,就弹出一个MessageBox,说“请选择至少一个文档。”

如果有帮助,TimeStampPdfs方法是:

private System.Threading.Tasks.Task TimeStampPdfs() => System.Threading.Tasks.Task.Run(() =>
    {
        for (int i = 0; i < documentsView.CheckedItems.Count; i++)
        {
            var currentDocument = documentsView.CheckedItems[i].ToString();
            if (!string.Equals(
                System.IO.Path.GetExtension(currentDocument), ".pdf", System.StringComparison.InvariantCultureIgnoreCase))
            {
                currentDocument = ConvertToPdf(currentDocument);
            }
            TimeStampPdf(currentDocument);
            Report(new ProgressReport
            {
                Total = documentsView.CheckedItems.Count,
                CurrentCount = i + 1
            });
        }
    }).ContinueWith(t =>
    {
        System.Windows.Forms.MessageBox.Show("Files saved with time-stamp on print script in " + OutputRootPath);
    },
        System.Threading.CancellationToken.None,
        System.Threading.Tasks.TaskContinuationOptions.OnlyOnRanToCompletion,
        System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext()
    );

我知道它会运行,因为显示“在...中打印脚本上带有时间戳的文件”消息框。

1 个答案:

答案 0 :(得分:1)

  

问题是即使条件为false(documentsView.CheckedItemsCount等于0),任务仍然会执行。

那是因为您的代码在此处开始TimeStampPdfs任务,调用PerformTask之前

await PerformTask(TimeStampPdfs());

换句话说,await 启动任务;相反,TimeStampPdfs启动任务并返回已在进行中的任务。 await然后(异步)等待完成的任务。您可能会发现我的async intro有帮助。

如果我正确理解您的代码,您可能希望传递一个返回任务的委托,如下所示:

private async Task PerformTask(Func<Task> func)
{
  if(documentsView.CheckedItems.Count > 0)
  {
    Enabled = false;
    try
    {
      await func();
    }
  ...
}


await PerformTask(() => TimeStampPdfs());

在旁注中,我建议await使用ContinueWith代替TimeStampPdfs

private async Task TimeStampPdfs()
{
  await Task.Run(() =>
  {
    ...
  });
  MessageBox.Show("Files saved with time-stamp on print script in " + OutputRootPath);
}