AFAIK,它所知道的只是在某些时候,它的SetResult或SetException方法被调用来完成通过Task属性暴露的Task<T>。
换句话说,它充当Task<TResult>及其完成的生产者。
我在这里看到了一个例子:
如果我需要一种方法来异步执行Func<T>,并有一个任务<T>
来表示这个操作。
public static Task<T> RunAsync<T>(Func<T> function)
{
if (function == null) throw new ArgumentNullException(“function”);
var tcs = new TaskCompletionSource<T>();
ThreadPool.QueueUserWorkItem(_ =>
{
try
{
T result = function();
tcs.SetResult(result);
}
catch(Exception exc) { tcs.SetException(exc); }
});
return tcs.Task;
}
如果我没有Task.Factory.StartNew -
但是我有task。factory。startnew。
问题:
有人能举例说明一个与TaskCompletionSource直接相关的场景吗
而不是假设没有task。factory。startnew ?
在这篇来自“。net并行编程”博客的文章中有一个真实的例子。你真的应该读一读,但这里有一个总结。
这篇博文展示了两种实现:
一种工厂方法,用于创建“延迟”任务,这些任务不会延迟
实际上,在发生用户提供的超时之前,都要进行调度。”
所示的第一个实现基于Task<>,有两个主要缺陷。第二篇实现文章继续使用TaskCompletionSource<>来缓解这些问题。
这是第二个实现:
public static Task StartNewDelayed(int millisecondsDelay, Action action)
{
// Validate arguments
if (millisecondsDelay < 0)
throw new ArgumentOutOfRangeException("millisecondsDelay");
if (action == null) throw new ArgumentNullException("action");
// Create a trigger used to start the task
var tcs = new TaskCompletionSource<object>();
// Start a timer that will trigger it
var timer = new Timer(
_ => tcs.SetResult(null), null, millisecondsDelay, Timeout.Infinite);
// Create and return a task that will be scheduled when the trigger fires.
return tcs.Task.ContinueWith(_ =>
{
timer.Dispose();
action();
});
}
在这篇博文中,Levi Botelho描述了如何使用TaskCompletionSource为Process编写异步包装器,这样您就可以启动它并等待它的终止。
public static Task RunProcessAsync(string processPath)
{
var tcs = new TaskCompletionSource<object>();
var process = new Process
{
EnableRaisingEvents = true,
StartInfo = new ProcessStartInfo(processPath)
{
RedirectStandardError = true,
UseShellExecute = false
}
};
process.Exited += (sender, args) =>
{
if (process.ExitCode != 0)
{
var errorMessage = process.StandardError.ReadToEnd();
tcs.SetException(new InvalidOperationException("The process did not exit correctly. " +
"The corresponding error message was: " + errorMessage));
}
else
{
tcs.SetResult(null);
}
process.Dispose();
};
process.Start();
return tcs.Task;
}
以及它的用法
await RunProcessAsync("myexecutable.exe");
在这篇来自“。net并行编程”博客的文章中有一个真实的例子。你真的应该读一读,但这里有一个总结。
这篇博文展示了两种实现:
一种工厂方法,用于创建“延迟”任务,这些任务不会延迟
实际上,在发生用户提供的超时之前,都要进行调度。”
所示的第一个实现基于Task<>,有两个主要缺陷。第二篇实现文章继续使用TaskCompletionSource<>来缓解这些问题。
这是第二个实现:
public static Task StartNewDelayed(int millisecondsDelay, Action action)
{
// Validate arguments
if (millisecondsDelay < 0)
throw new ArgumentOutOfRangeException("millisecondsDelay");
if (action == null) throw new ArgumentNullException("action");
// Create a trigger used to start the task
var tcs = new TaskCompletionSource<object>();
// Start a timer that will trigger it
var timer = new Timer(
_ => tcs.SetResult(null), null, millisecondsDelay, Timeout.Infinite);
// Create and return a task that will be scheduled when the trigger fires.
return tcs.Task.ContinueWith(_ =>
{
timer.Dispose();
action();
});
}
TaskCompletionSource is used to create Task objects that don't execute code.
In real world scenarios, TaskCompletionSource is ideal for I/O bound operations. This way, you get all the benefits of tasks (e.g. return values, continuations, etc) without blocking a thread for the duration of the operation. If your "function" is an I/O bound operation, it isn't recommended to block a thread using a new Task. Instead, using TaskCompletionSource, you can create a slave task to just indicate when your I/O bound operation finishes or faults.