我正在模式对话框的后台线程中执行可能长时间运行的操作。问题是,当操作花费很短的时间时,对话框几乎立即显示并关闭,这使用户感到烦恼。
我只想在操作花费比2s更长的时间显示对话框。
该对话框是WPF窗口,并且长时间运行的操作代码在ViewModel中。 ViewModel创建一个Task,该Task在后台运行该操作。
以下是相关片段:
public Task StartAction() {
var mainTask = Task.Factory.StartNew(InternalAction);
MainTask = mainTask;
mainTask.ContinueWith(_ => { IsFinished = true; });
return mainTask;
}
InternalAction
是可能会长时间运行的操作。这就是我试图引入延迟的方式。我正在使用来自其他answer的Sriram Sakthivel的建议,但是代码并不完全相同:
var viewModel = ... // Creates the ViewModel
var dialogWindow = ... // Creates the Window and starts the operation by calling viewModel.StartAction();
var delayTask = Task.Delay(2000);
if (viewModel.MainTask != null) {
Task.WaitAny(delayTask, viewModel.MainTask);
}
if (viewModel.IsFinished) {
return;
}
ShowDialog(dialogWindow); // this code calls dialogWindow.ShowDialog() eventually
我不使用
await
,因为我不希望将控制权交给调用方(COM),因为调用方希望返回控件时可以准备好结果。我一直在尝试不同的超时时间,例如5000毫秒,但在行为上没有任何差异。对话框窗口仍然“闪烁”(显示并立即关闭)。我确定我做错了什么,但我无法理解我的错误。
最佳答案
您正在等待MainTask
,但MainTask
不是设置IsFinished
的任务。您可能在WaitAny
完成之后但在InternalAction
延续完成之前从IsFinished = true
返回。
尝试将MainTask
设置为延续,而不是其前身:
public Task StartAction() {
var mainTask = Task.Factory.StartNew(InternalAction);
var continuation = mainTask.ContinueWith(_ => { IsFinished = true; });
MainTask = continuation;
return mainTask;
}
请注意,
continuation
在mainTask
完成之前无法开始,因此通过此更改,您将等待mainTask
和continuation
。但是请注意,如果正在从UI线程读取
IsFinished
,则还需要从UI线程进行设置。那,或者使其由volatile
字段作为后盾。
关于c# - WPF:仅当其后台任务花费的时间超过指定间隔时,才显示进度对话框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48569185/