2015-06-11 2 views
0

У меня есть класс, у которого есть несколько заданий, которые созданы и происходят. Когда я запускаю мой тестовый пример приложения из потоков, созданных/используемых в следующем ...Использование Task.Factory.StartNew() Then Возвращаемое значение

  • Thread9 (Главная тема)
  • Thread9
  • Thread9
  • Thread10 (рабочий StartNew Thread)
  • Thread11 (рабочий ContinueWith Thread)
  • Thread11

Я могу передать объект из моего основного потока (9) в рабочий поток (10) и из рабочего потока в рабочий ContinueWith thread (11) [AKA завершение рабочего потока (10)]. Все, что я делаю, отлично работает с одним исключением ... Я не могу вернуть этот объект в основной поток, используя что-то вроде события. Всякий раз, когда я пытаюсь делегировать или вызывать обратно в основной поток, это не сработает. Он всегда срабатывает на Thread11 вместо Thread9!

Моя цель - вернуть объект (используемый в Thread11) обратно в главную Thread9.

Примечания:

  • Я не могу использовать .Wait() или приостановить MainUI каким-либо образом.
  • Я не могу использовать Task.WaitAll() или Task.WaitAny(), так как это также заморозит пользовательский интерфейс.
  • Invoke не будет работать, потому что это пользовательский класс, а не форма.

ОБНОВЛЕНО - Пример:

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 изменяется на «Третье изменение» и она будет возвращен мне нужен какой-то тип события, чтобы быть поднятым или что-то, чтобы получить результаты обратно в основной поток пользовательского интерфейса 9.

+1

Вы пробовали использовать асинхра/ждете вместе с этими задачами? –

+0

Добавлен небольшой пример. Это лучше объясняет это? @Ron, ожидание нужно будет вызвать сразу после создания/запуска задачи и остановки основного потока пользовательского интерфейса, не так ли? –

+0

Нашел эту приятную статью о async/await. http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx, но все еще не могут понять, как их использование будет полезно для моей ситуации. Может быть, добавьте ответ, чтобы показать мне, о чем вы говорите? Также, как этот вопрос не по теме? Это связано с программированием и идеально подходит для SO ... –

ответ

0

Как @ r00tdev объяснил, используя класс SynchronizationContext() является решением, что я пытался сделать. Ниже вы увидите пример того, как я использовал его, чтобы вернуть результаты рабочего потока в основной поток пользовательского интерфейса. Спасибо за ответ @ 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; 
} 
0

вам нужно использовать _synchronizationContext.Send или _synchronizationContext.Post общаться с Пользовательский интерфейс.

Кроме того, из того, что вы упомянули, я думаю, вам также нужно передать «ложь» при вызове любой из вышеперечисленных функций, чтобы он знал, что функция не вызывается из потока пользовательского интерфейса.

_synchronizationContext = SynchronizationContext.Current 
+0

Спасибо @ r00tdev Я сделаю снимок. Думаете, вы могли бы привести пример случайно? –

+0

Предоставляйте ограниченным ресурсам MSDN по этому вопросу. Мне пришлось обратиться к этой странице с большим художественным текстом в SynchronizationContext. Это звучит ТОЧНО, что мне нужно! Я даю ему попробовать, и если это сработает, я дам вам ответ. Я могу обновить ответ на примере, если вы не дойдете до него в первую очередь. ;) http://www.codeproject.com/Articles/31971/Understanding-SynchronizationContext-Part-I –

+0

Ну @ ​​r00tdev извините, я попытался дать вам ответ, но кажется, что голоса пришли от 3 до 2 (не в пользу моего редактирования, добавив пример). Поэтому он заставил меня добавить свой ответ.Ответы гораздо более полезны с примером, и я не могу себе представить, почему в мире мое редактирование было бы отвергнуто, было явно УЛУЧШИТЬ ответ для сообщества ... –

Смежные вопросы