c# - WPF:仅当其后台任务花费的时间超过指定间隔时,才显示进度对话框

标签 c# wpf mvvm task

我正在模式对话框的后台线程中执行可能长时间运行的操作。问题是,当操作花费很短的时间时,对话框几乎立即显示并关闭,这使用户感到烦恼。
我只想在操作花费比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;
}  

请注意,continuationmainTask完成之前无法开始,因此通过此更改,您将等待mainTaskcontinuation

但是请注意,如果正在从UI线程读取IsFinished,则还需要从UI线程进行设置。那,或者使其由volatile字段作为后盾。

关于c# - WPF:仅当其后台任务花费的时间超过指定间隔时,才显示进度对话框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48569185/

相关文章:

c# - WinForm 与 WPF .Close() 事件

wpf - 如何在另一个 xaml 的控件上应用双动画?

xaml - CalendarDatePicker 在第二次选择相同的日期时返回 null

wpf - 在 DataTemplate 中绑定(bind) Grid.Row/Grid.Column

c# - System.PlatformNotSupportedException AesCryptoServiceProvider

c# - 如何跨线程获取 control.Handle 属性

c# - UI本地化

c# - 如何从不同的程序读取另一个窗口

c# - 合并词典的噩梦

mvvm - 如何在mvvm中绑定(bind)多个同步融合xamarin表单数据网格?