Как задача TPL может отправлять промежуточные результаты в родительский поток? - PullRequest
3 голосов
/ 04 октября 2011

Я работаю с TPL, и мне нужно, чтобы длительное задание TPL отправляло результаты в родительский поток пользовательского интерфейса без прерывания.Я пробовал несколько подходов и довольно много гуглил.Кто-нибудь знает, как это сделать с TPL?

Ответы [ 2 ]

5 голосов
/ 04 октября 2011

Вы можете передать делегат для вызова с периодическими результатами и SynchronizationContext, который задача может использовать для вызова обратного вызова в правильном потоке. Это в основном способ, которым BackgroundWorker делает это (и способ, которым функция асинхронности C # 5 будет «знать», куда вам перезвонить) - он захватывает SynchronizationContext.Current в вызывающем потоке, затем вызывает Post (IIRC), чтобы опубликовать сообщение в нужном контексте. Затем вам просто нужно обернуть исходный обратный вызов в SendOrPostCallback, который выполняет его, когда он попадает в нужный поток.

РЕДАКТИРОВАТЬ: Пример программы:

using System;
using System.Windows.Forms;
using System.Threading;
using System.Threading.Tasks;

class Test
{
    static void Main()
    {
        Form form = new Form();
        Label label = new Label();
        form.Controls.Add(label);
        form.Load += delegate { HandleLoaded(label); };
        Application.Run(form);
    }

    static void HandleLoaded(Label label)
    {
        Action<string> callback = text => label.Text = text;
        StartTask(callback);
    }

    static void StartTask(Action<string> callback)
    {
        SendOrPostCallback postCallback = obj => callback((string) obj);
        SynchronizationContext context = SynchronizationContext.Current;

        Task.Factory.StartNew(() => {
            for (int i = 0; i < 100; i++)
            {
                string text = i.ToString();
                context.Post(postCallback, text);
                Thread.Sleep(100);
            }
        });
    }
}
0 голосов
/ 04 октября 2011

В зависимости от используемого вами приложения могут быть разные подходы.

  • WinForms: Control.Invoke
  • WPF / Silverlight / WP7 и производные: Dispatcher.Invoke
  • Какой-то другой тип приложения: определите, что Поток пользовательского интерфейса означает первым?
...