在ShowDialog()之后使用线程运行代码

在您回复之前,我了解ShowDialog的工作并且它是同步的。我还查看了thread,他们在回答中谈到了后台工作人员和线程。

我正在尝试为我的项目制作进度条,但是当工作完成时,他们不应该与主窗口进行交互(这就是为什么它需要为ShowDialog的原因)。因此,我提供了此解决方案,但是由于零线程经验,我不知道这是否是一个好的解决方案。

这只是该解决方案的一些模型代码,其工作方式与预期的目的相同。

private async void Button_Click(object sender,RoutedEventArgs e)
{
    Window1 progress_Bar = new Window1();
    Thread test = new Thread(() => test_method(progress_Bar));
    test.Start();
    for (int i = 0; i < 11; i++)
    {
        //work
        progress_Bar.Bar.Value = i;
        await Task.Delay(1000);
    }
    progress_Bar.Close();
    test.Abort();
}

private void test_method(Window1 _Test)
{
    _Test.Dispatcher.Invoke(() =>
    {
        _Test.ShowDialog();
    });
}

其中:Window1只是我正在打开的窗口窗体,用户在工作完成时看到,而.Bar是进度条。

所以我的主要问题是,这是使用线程正确的还是我应该研究其他内容(请不要给出是或否的答案)。

欢迎任何答复,如果还有其他解决方法,请告诉我!谢谢。

douyang 回答:在ShowDialog()之后使用线程运行代码

为此您需要一个异步ShowDialog方法

public static class WindowExtensions
{
    public static async Task<bool?> ShowDialogAsync(this Window window)
    {
        await Task.Yield(); // this is the magic ;o)
        return window.ShowDialog();
    }
}

现在您可以做

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private async void Button_Click( object sender,RoutedEventArgs e )
    {
        var dialog = new WaitWindow();
        var task = WorkAsync( dialog.Progress );
        var dialogTask = dialog.ShowDialogAsync();
        await task;
        dialog.Close();
        await dialogTask;
    }

    private async Task WorkAsync( IProgress<double> progress )
    {
        for ( int i = 0; i < 100; i++ )
        {
            progress.Report( i );
            await Task.Delay( 25 ).ConfigureAwait( false );
        }
    }
}

WaitWindow类

public partial class WaitWindow : Window
{
    public WaitWindow()
    {
        InitializeComponent();

        Progress = new Progress<double>( progress => ProgressHandler( progress ) );
    }

    public IProgress<double> Progress { get; }

    private void ProgressHandler( double progress )
    {
        progressBar.Value = progress;
    }
}
,

我会研究IProgress T界面。

创建一个类,该类将保存您的进度信息,例如进度值,最大值,最小值(如果需要)。

public class MyProgressReport
{
    public int ProgressValue{ get; set; }
}

在类中某个位置的ReportProgress方法将获取进度报告并更新用户界面上的信息

private void ReportProgress(MyProgressReport progressReport)
{
    //your dialog window needs a property to handle progress
    //or just access its Bar.Value like you do in your example
    dialogWindow.Progress = progressReport.ProgressValue;
}

最后是显示对话框/完成工作的方法。告诉它您想使用Action做什么。

public async void ShowBusyWindow(Action<IProgress<MyProgressReport>> operation)
{
    //ReportProgress method will be called every time you want to update progress
    var progressCallback = new Progress<MyProgressReport>(ReportProgress);

    progressWindow = new Window();

    var workTask = DoWork(operation(progressCallback));
    progressWindow.ShowDialog(); //program will wait here until window is closed
    await workTask; // usually not needed since workTask will be done by the time this is hit,this is where exceptions will be thrown
}

private async Task DoWork(Action operation)
{
    //you should also check for exceptions here and close window
    await Task.Run(operation);
    //close window when done
    progressWindow.Close();
}

最后,要使用它,您只需像这样调用Show:

ShowBusyWindow((progress) => 
{
    //do work here and update progress
    var report = new MyProgressReport();

    for(int i=0; i<100; i++)
    {
        report.ProgressValue = i;
        progress.Report(report);
        Thread.Sleep(500);
    }
});

我还没有运行它(可能会出现错误),但是我使用了几乎相同的方法,在进度报告类和异常处理上有更多的属性。

本文链接:https://www.f2er.com/3110312.html

大家都在问