Вы можете передать делегат для вызова с периодическими результатами и 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);
}
});
}
}