首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何从WPF gui运行异步任务并与之交互

如何从WPF gui运行异步任务并与之交互
EN

Stack Overflow用户
提问于 2014-11-23 21:03:58
回答 1查看 95.3K关注 0票数 80

我有一个WPF GUI,我想在其中按一个按钮来启动一个长任务,而不会在任务持续时间内冻结窗口。当任务正在运行时,我希望获得进度报告,并且我希望加入另一个按钮,该按钮将在我选择的任何时间停止任务。

我想不出使用async/await/task的正确方法。我不能包括我尝试过的所有东西,但这就是我目前所拥有的。

WPF窗口类:

代码语言:javascript
复制
public partial class MainWindow : Window
{
    readonly otherClass _burnBabyBurn = new OtherClass();
    internal bool StopWorking = false;
        
    //A button method to start the long running method
    private async void Button_Click_3(object sender, RoutedEventArgs e)
    {   
        Task slowBurn = _burnBabyBurn.ExecuteLongProcedureAsync(this, intParam1, intParam2, intParam3);
            
        await slowBurn;
    }
        
    //A button Method to interrupt and stop the long running method
    private void StopButton_Click(object sender, RoutedEventArgs e)
    {
        StopWorking = true;
    }

    //A method to allow the worker method to call back and update the gui
    internal void UpdateWindow(string message)
    {
        TextBox1.Text = message;
    }
}

还有一个用于worker方法的类:

代码语言:javascript
复制
class OtherClass
{
    internal Task ExecuteLongProcedureAsync(MainWindow gui, int param1, int param2, int param3)
    {       
        var tcs = new TaskCompletionSource<int>();       
             
        //Start doing work
        gui.UpdateWindow("Work Started");        
             
        While(stillWorking)
        {
        //Mid procedure progress report
        gui.UpdateWindow("Bath water n% thrown out");        
        if (gui.StopTraining) return tcs.Task;
        }
             
        //Exit message
        gui.UpdateWindow("Done and Done");       
        return tcs.Task;        
    }
}

这会运行,但WPF函数窗口在worker方法启动后仍会被阻塞。

我需要知道如何安排async/await/task声明以允许

A)不阻塞gui窗口的worker方法。

B)让worker方法更新gui窗口。

C)允许gui窗口停止中断并停止工作方法

任何帮助或指点都是非常感谢的。

EN

回答 1

Stack Overflow用户

发布于 2014-11-24 03:50:35

您对TaskCompletionSource<T>的使用不正确。TaskCompletionSource<T>是一种为异步操作创建TAP-compatible wrappers的方法。在您的ExecuteLongProcedureAsync方法中,示例代码都是受CPU限制的(即,本质上是同步的,而不是异步的)。

因此,将ExecuteLongProcedure编写为同步方法要自然得多。对标准行为使用标准类型也是一个好主意,特别是using IProgress for progress updatesCancellationToken for cancellation

代码语言:javascript
复制
internal void ExecuteLongProcedure(int param1, int param2, int param3,
    CancellationToken cancellationToken, IProgress<string> progress)
{       
  //Start doing work
  if (progress != null)
    progress.Report("Work Started");

  while (true)
  {
    //Mid procedure progress report
    if (progress != null)
      progress.Report("Bath water n% thrown out");
    cancellationToken.ThrowIfCancellationRequested();
  }

  //Exit message
  if (progress != null)
    progress.Report("Done and Done");
}

现在,您有了一个使用适当约定的更可重用的类型(没有GUI依赖项)。它可以这样使用:

代码语言:javascript
复制
public partial class MainWindow : Window
{
  readonly otherClass _burnBabyBurn = new OtherClass();
  CancellationTokenSource _stopWorkingCts = new CancellationTokenSource();

  //A button method to start the long running method
  private async void Button_Click_3(object sender, RoutedEventArgs e)
  {
    var progress = new Progress<string>(data => UpdateWindow(data));
    try
    {
      await Task.Run(() => _burnBabyBurn.ExecuteLongProcedure(intParam1, intParam2, intParam3,
          _stopWorkingCts.Token, progress));
    }
    catch (OperationCanceledException)
    {
      // TODO: update the GUI to indicate the method was canceled.
    }
  }

  //A button Method to interrupt and stop the long running method
  private void StopButton_Click(object sender, RoutedEventArgs e)
  {
    _stopWorkingCts.Cancel();
  }

  //A method to allow the worker method to call back and update the gui
  void UpdateWindow(string message)
  {
    TextBox1.Text = message;
  }
}
票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27089263

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档