我有一个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()
);
我知道它会运行,因为显示“在...中打印脚本上带有时间戳的文件”消息框。
答案 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);
}