使用 task.Factory.StartNew() 然后返回值

本文关键字:然后 返回值 StartNew task Factory 使用 | 更新日期: 2023-09-27 17:55:34

我有一个类,其中包含一些创建和发生的任务。 当我运行我的测试应用程序时,创建/使用的线程示例如下......

    线程
  • 9(主线程)
  • 线程9
  • 线程9
  • 线程
  • 10(工作线程启动新线程)
  • 线程
  • 11(工作线程继续)
  • 线程11

我能够将对象从我的主线程 (9) 传递到工作线程 (10) 中,并从工作线程传递到工作线程 ContinueWith thread(11) [又名完成工作线程 (10)]。 我所做的一切都很好,只有一个例外...... 我似乎无法使用类似事件之类的东西将该对象返回到主线程。 每当我尝试委托或调用回主线程时,它都不会起作用。 它总是在线程 11 而不是线程 9 上触发!

我的目标是将对象(在 Thread11 中使用)返回到主 Thread9。

笔记:

  • 我不能使用.Wait() 或以任何方式暂停 MainUI。
  • 我不能使用Task.WaitAll()或Task.WaitAny(),因为它也会冻结UI。
  • 调用将不起作用,因为这是一个自定义类而不是一个窗体。

已更新 - 示例:

private SQLConnectionProperties sql = new SQLConnectionProperties();
private void SQLTest()
{
    //Being called from main UI thread 9
    sql.SQLErrorMessage = "FIRST CHANGE";
    Task<SQLConnectionProperties> taskConnect = Task.Factory
        .StartNew(() => threadConnect(sql), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default)
        .ContinueWith((task) => threadConnect(task.Result, true));
    //Continue back to main UI (still in main UI thread 9)
}
private SQLConnectionProperties threadConnect(SQLConnectionProperties sql, bool bContinuation = false)
{
    if (!bContinuation)
    {
        //In new thread 10
        sql.SQLErrorMessage = "SECOND CHANGE";
    }
    else
    {
        //In new thread 11
        sql.SQLErrorMessage = "THIRD CHANGE";
    }
    return sql;
}

使用上面的代码,我将拥有我想要的一切,直到In new thread 11行。 在SQLErrorMessage更改为"THIRD CHANGE"并返回后,我需要引发某种类型的事件或将结果返回到主UI线程9。

使用 task.Factory.StartNew() 然后返回值

您需要

使用 _synchronizationContext.Send_synchronizationContext.Post 与 UI 线程通信。

另外,从

您提到的内容来看,我认为您在调用上述任一函数时还需要传递"false",以便它知道该函数不是从 UI 线程调用的。

_synchronizationContext = SynchronizationContext.Current

正如@r00tdev所解释的,使用 SynchronizationContext() 类是我尝试执行的操作的解决方案。 下面您将看到一个示例,说明我如何使用它将工作线程的结果返回到主 UI 线程。 感谢您@r00tdev回答!


例:

private void SQLTest()
{
    //Set up a sync context back to this main UI thread
    m_sql.SyncContext = SynchronizationContext.Current;
    //Being called from main UI thread 9
    m_sql.SQLErrorMessage = "FIRST CHANGE";
    Task<SQLConnectionProperties> taskConnect = Task.Factory
        .StartNew(() => threadConnect(m_sql), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default)
        .ContinueWith((task) => threadConnect(task.Result, true));
    //Continue back to main UI (still in main UI thread 9)
}
private SQLConnectionProperties threadConnect(SQLConnectionProperties sql, bool bContinuation = false)
{
    if (!bContinuation)
    {
        //In new thread 10
        sql.SQLErrorMessage = "SECOND CHANGE";
    }
    else
    {
        //In new thread 11
        sql.SQLErrorMessage = "THIRD CHANGE";
        sql.SyncContext.Post(threadConnectComplete, sql);
    }
    return sql;
}
private void threadConnectComplete(object state)
{
    //Back in the main UI thread!  Save the changes to the sql object
    SQLConnectionProperties sql = state as SQLConnectionProperties;
    m_sql = sql;
    //See the results and use this area to update the main UI
    Debug.WriteLine("SQLErrorMessage:" + sql.SQLErrorMessage);
    //TESTING NON THREAD SAFE just to show you no runtime errors happen
    form_MainUI.textbox1.Text = sql.SQLErrorMessage;
}