WPF – Task.Run(()=gt; window.ShowDialog)失败
副标题[/!--empirenews.page--]
我必须实施忙碌指示和进度报告.约束是,我必须使用提供的控制库,它提供了一个进度报告窗口. 以下代码工作正常,但不会阻止UI,这在某些时候是必需的. private async void StartLongRunningTask2Sync() { var wndHandle = Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive); if (wndHandle == null) { return; } IntPtr windowHandle = new WindowInteropHelper(wndHandle).Handle; var progressWindow = new ProgressBarCustomized(windowHandle) { Value = 0,CanCancel = true,CanRetry = false,Thumbnail = null,IsIndeterminate = true }; progressWindow.Show(); await Task.Run(() => this.longRunningTaskComponent.DoLongRunningTask(this.taskIterations,this.iterationSleepTime)); progressWindow.Close(); } 阻止UI的以下代码到目前为止可以打开对话框,但是在对话框再次关闭之前,长时间运行的任务永远不会执行: private async void StartLongRunningTask2Sync() { var wndHandle = Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive); if (wndHandle == null) { return; } IntPtr windowHandle = new WindowInteropHelper(wndHandle).Handle; var progressWindow = new ProgressBarCustomized(windowHandle) { Value = 0,IsIndeterminate = true }; progressWindow.ShowDialog(); await Task.Run(() => this.longRunningTaskComponent.DoLongRunningTask(this.taskIterations,this.iterationSleepTime)); progressWindow.Close(); } 所以我尝试了这种方法: private async void StartLongRunningTask2Sync() { var wndHandle = Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive); if (wndHandle == null) { return; } IntPtr windowHandle = new WindowInteropHelper(wndHandle).Handle; var progressWindow = new ProgressBarCustomized(windowHandle) { Value = 0,IsIndeterminate = true }; Task.Run(() => progressWindow.ShowDialog()); await Task.Run(() => this.longRunningTaskComponent.DoLongRunningTask(this.taskIterations,this.iterationSleepTime)); progressWindow.Close(); } 这样做时,我收到以下错误: 在调查我发现的自定义进度窗口后,调用“base.ShowDialog()”会抛出此错误. 有没有办法做我喜欢或做的事情我必须用完全不同的方法做到这一点? 更新: 那么“真实”的问题: 解决方法
你已经获得了大部分作品;你只需要把它们放在一起.
所有UI都应该在单个GUI线程上.这不是绝对必要的,但它是一个很好的简化器,适用于绝大多数应用程序.在UI世界中,“阻塞窗口”被称为“模态对话框”,您可以通过调用ShowDialog来显示它. // Start the long-running operation var task = LongRunningOperationAsync(); // Show the dialog progressWindow.ShowDialog(); // Retrieve results / propagate exceptions var results = await task;
为此,您需要连接完成任务以关闭窗口.使用async / await非常简单: async Task DoOperationAsync(ProgressWindow progressWindow) { try { await LongRunningOperationAsync(); } finally { progressWindow.Close(); } } // Start the long-running operation var task = DoOperationAsync(progressWindow); // Show the dialog progressWindow.ShowDialog(); // Retrieve results / propagate exceptions var results = await task;
假设您的操作使用标准IProgress< T>报告进度的界面: async Task DoOperationAsync(Window progressWindow,IProgress<int> progress) { try { await LongRunningOperationAsync(progress); } finally { progressWindow.Close(); } } var progressWindowVM = ...; var progress = new Progress<int>(value => { progressWindowVM.Progress = value; }); var task = DoOperationAsync(progressWindow,progress); progressWindow.ShowDialog(); var results = await task; 另一个需要考虑的常见用例是,如果用户自己关闭进度对话框,则取消操作.同样,如果您的操作已经使用标准的CancellationToken,这是直截了当的: async Task DoOperationAsync(Window progressWindow,CancellationToken token,IProgress<int> progress) { try { await LongRunningOperationAsync(token,progress); } catch (OperationCanceledException) { } finally { progressWindow.Close(); } } var progressWindowVM = ...; var progress = new Progress<int>(value => { progressWindowVM.Progress = value; }); var cts = new CancellationTokenSource(); progressWindow.Closed += (_,__) => cts.Cancel(); var task = DoOperationAsync(progressWindow,cts.Token,progress); progressWindow.ShowDialog(); var results = await task;
(编辑:好传媒网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |