首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Task.Factory.StartNew()然后返回值

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

Stack Overflow用户
提问于 2015-06-11 02:56:44
回答 2查看 1.2K关注 0票数 1

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

  • Thread9 (主线程)
  • Thread9
  • Thread9
  • Thread10 (Worker StartNew Thread)
  • Thread11 (Worker ContinueWith Thread)
  • Thread11

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

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

备注:

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

更新-实例:

代码语言:javascript
复制
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更改为“第三个更改”并返回之后,我需要引发某种类型的事件,或者将结果返回到主UI线程9。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-06-11 16:55:31

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

示例:

代码语言:javascript
复制
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;
}
票数 0
EN

Stack Overflow用户

发布于 2015-06-11 04:01:50

您需要使用_synchronizationContext.Send_synchronizationContext.Post与UI线程进行通信。

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

代码语言:javascript
复制
_synchronizationContext = SynchronizationContext.Current
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30770788

复制
相关文章

相似问题

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