gpt4 book ai didi

multithreading - 如何在没有主线程等待的情况下从长时间运行的后台任务中引发异常

转载 作者:行者123 更新时间:2023-12-03 12:52:39 25 4
gpt4 key购买 nike

我想在后台线程上执行一些长时间运行的操作(例如监听操作系统引发的一些事件)。大多数情况下,操作会连续运行而不会出现任何问题。但是在某些罕见的情况下,操作系统级别的 API 会发送一些错误代码,我需要从后台线程引发异常,该异常必须传播到主线程以将其显示给我的 WinFrom 的用户应用。

我决定使用 BackgroundWorker为了这。但是 .NET 4.0 提供了 Task Task Parallel Library 的类别根据 TPL 上的各种博客,这是一个更好的选择。

在我的应用程序中,我必须在显示实际表单之前启动后台任务。由于实际代码相当复杂,我编写了一些模拟实时问题的示例代码:

public static Task task;

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
ThreadTest tt = new ThreadTest();
task = new Task(() => tt.PerformTask("hi"));
task.Start();
try
{
task.Wait();
}
catch (AggregateException aggregateException)
{
// Handle exception here.
}

Application.Run(new Form1());
}

在这段代码中,我从来没有看到主窗体,因为后台任务一直在无异常运行,并且 task.Wait() call 使当前线程等待直到后台任务完成!

我可以使用 TPLTask对于主线程不应该等到后台任务完成但同时,它应该在后台任务引发异常时获取异常详细信息的情况?

在上面的代码中,解决方案之一可能是在稍后阶段移动任务创建代码。但在这种情况下,我的问题更具学术性。

最佳答案

是的你可以。请看下面的代码。

  • 程序代码为:
         /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

    Task longRunningTask = new Task((state) =>
    {
    LongRunningWork.DoWork( cancellationTokenSource.Token);

    },cancellationTokenSource.Token,TaskCreationOptions.LongRunning);

    var newForm = new Form1(cancellationTokenSource);
    new Thread((state) =>
    {
    longRunningTask.Start();

    try
    {
    longRunningTask.Wait();
    }
    catch (AggregateException exception)
    {
    Action<Exception> showError = (ex) => MessageBox.Show(state as Form, ex.Message);

    var mainForm = state as Form;
    if (mainForm != null)
    {
    mainForm.BeginInvoke(showError, exception.InnerException);
    }

    }
    }).Start(newForm);
    Application.Run(newForm);
  • 长时间运行的任务的代码是:
    public class LongRunningWork
    {
    public static void DoWork( CancellationToken cancellationToken)
    {

    int iterationCount = 0;
    //While the
    while (!cancellationToken.IsCancellationRequested &&iterationCount <5)
    {
    //Mimic that we do some long jobs here
    Thread.Sleep(1000);

    iterationCount++;
    //The jobs may throw the exception on the specific condition
    if (iterationCount ==5)
    {
    throw new InvalidOperationException("Invalid action");
    }


    }

    //cancel the task
    cancellationToken.ThrowIfCancellationRequested();
    }
    }
  • 最后,Form1 的代码包含一个退出按钮,其功能是在单击时终止程序。

    公共(public)部分类Form1:表格
    {
        private CancellationTokenSource _cancellationTokenSource;

    public Form1()
    {
    InitializeComponent();
    }

    public Form1(CancellationTokenSource cancellationTokenSource):this()
    {
    _cancellationTokenSource = cancellationTokenSource;
    }

    private void exitBtn_Click(object sender, EventArgs e)
    {
    //Cancel out the task
    if (_cancellationTokenSource != null)
    {
    _cancellationTokenSource.Cancel();
    }

    //Exit the program
    Application.Exit();

    }
    }
  • 关于multithreading - 如何在没有主线程等待的情况下从长时间运行的后台任务中引发异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14038137/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com