如何强制Task.Factory.StartNew到后台线程?(How to force Task.

2019-08-22 02:23发布

我见过类似这样的许多其他问题,但并没有发现我的回答有。

我的问题是,我是创建一个与下面的流程线:

private void btn_Click(object sender, EventArgs e)
{
    service.GetCount(
        (count, ex) =>
        {
            if (ex != null)
                return;

            for (int i = 0; i < count; i++)
            {
                service.Get(onItemReceived, i);
            }
        }
    );
}

public void GetCount(Action<int, Exception> callback)
{
    var callingThread = TaskScheduler.FromCurrentSynchronizationContext();

    Func<int> action = () =>
    {
        return client.GetCount(); // Synchronous method, could take a long time
    };

    Action<Task<int>> completeAction = (task) =>
    {
        Exception ex = (task.Exception != null) ? task.Exception.InnerException : task.Exception;

        if (callback != null)
            callback(task.Result, ex);
    };

    Task.Factory.StartNew(action).ContinueWith(completeAction, callingThread);
}

public void Get(Action<object, Exception> callback, int index)
{
    var callingThread = TaskScheduler.FromCurrentSynchronizationContext();

    Func<object> action = () =>
    {
        return client.Get(index); // Synchronous method, could take a long time
    };

    Action<Task<object>> completeAction = (task) =>
    {
        Exception ex = (task.Exception != null) ? task.Exception.InnerException : task.Exception;

        if (callback != null)
            callback(task.Result, ex);
    };

    Task.Factory.StartNew(action).ContinueWith(completeAction, callingThread);
}

这样一来,我的每一个服务的异步方法会回调,他们最初被称为上线(通常是UI线程)。 所以我模拟如何的await /异步关键字的工作(我不能使用.NET 4.5)。

这种模式的问题是,我就莫名锁定在UI线程第一次调用“ContinueWith”之后。 因此,在这种情况下,如果我试图产卵5个线程每个进程的同步功能, 那么他们就将以1而不是并行执行1,他们将阻止用户界面线程,而这样做,即使我尝试指定TaskCreationOptions.LongRunning。

这从来没有与我的第一次调用Task.Factory.StartNew发生,它只是发生从第一回调中后续调用。

Answer 1:

为了强制推出一个新的线程,你应该在调用Task.Factory.StartNew指定TaskScheduler.Default如下:

Task.Factory.StartNew(action,
                      CancellationToken.None,
                      TaskCreationOptions.None,
                      TaskScheduler.Default).ContinueWith(completeAction);

在我的测试,你不需要为了迫使后台线程指定TaskCreationOptions.LongRunning,虽然它不应该伤害。



文章来源: How to force Task.Factory.StartNew to a background thread?