wordpress   发布时间:2022-04-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了WPF – Task.Run(()=> window.ShowDialog)失败大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

概述

我必须实施忙碌指示和进度报告.约束是,我必须使用提供的控制库,它提供了一个进度报告窗口. 以下代码工作正常,但不会阻止UI,这在某些时候是必需的. private async void StartLongRunningTask2Sync() { var wndHandle = Application.Current.Windows.OfType<Window>().SingLeorDefault(
我必须实施忙碌指示和进度报告.约束是,我必须使用提供的控制库,它提供了一个进度报告窗口.

以下代码工作正常,但不会阻止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()”会抛出此错误.

有没有办法做我喜欢或做的事情我必须用完全不同的方法做到这一点?
最好的祝福

更新:
是的,我已经搜索了这个错误,是的,我已经尝试了几种方法与Dispatcher.Invoke()等…

那么“真实”的问题:
如何在长时间运行的任务运行时显示阻塞窗口,并在长时间运行的任务完成后关闭它,并最终通知窗口有关操作进度的信息.解决方案应该(最好)使用MVVM模式,而不是依赖(太多)代码.

解决方法

你已经获得了大部分作品;你只需要把它们放在一起.

所有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;
@H_759_19@mVVM在单个窗口中运行良好.一旦你开始尝试数据绑定窗口级别的操作和属性,它就会崩溃.这不是因为MVVM是一个糟糕的模式,而是因为很多MVVM框架都不能很好地处理这个问题.

上面的示例代码仅使用数据绑定将进度报告给进度对话框.如果您的MVVM框架可以数据绑定模式窗口的显示/隐藏,那么您可以使用我的NotifyTaskCompletion type驱动它.此外,一些框架具有更优雅(MVVM)的方式来处理Window.Closed,但细节取决于您的框架.

大佬总结

以上是大佬教程为你收集整理的WPF – Task.Run(()=> window.ShowDialog)失败全部内容,希望文章能够帮你解决WPF – Task.Run(()=> window.ShowDialog)失败所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。