C# 如何为HttpClient.GetStreamAsync()等异步方法编写代码?
详细说明一下,我想知道的是如何异步启动任务,就像在HttpClient.GetStreamAsync()等异步方法中所做的那样 示例代码如下所示:C# 如何为HttpClient.GetStreamAsync()等异步方法编写代码?,c#,async-await,c#-5.0,C#,Async Await,C# 5.0,详细说明一下,我想知道的是如何异步启动任务,就像在HttpClient.GetStreamAsync()等异步方法中所做的那样 示例代码如下所示: static async Task<string> LengthyOperation() { Console.WriteLine("Executing a lengthy operation..."); Debug.WriteLine("LENGTHY THREAD ID: " + Thre
static async Task<string> LengthyOperation()
{
Console.WriteLine("Executing a lengthy operation...");
Debug.WriteLine("LENGTHY THREAD ID: " + Thread.CurrentThread.ManagedThreadId);
var task = new Task(() =>
{
Debug.WriteLine("TASK THREAD ID: " + Thread.CurrentThread.ManagedThreadId);
for (int i = 0; i < 10000; i++)
{
File.ReadAllLines("abc.txt");
counter++;
}
});
task.Start();
await task;
}
静态异步任务长度操作()
{
WriteLine(“执行冗长的操作…”);
WriteLine(“冗长的线程ID:+THREAD.CurrentThread.ManagedThreadId”);
变量任务=新任务(()=>
{
WriteLine(“任务线程ID:+THREAD.CurrentThread.ManagedThreadId”);
对于(int i=0;i<10000;i++)
{
ReadAllLines(“abc.txt”);
计数器++;
}
});
task.Start();
等待任务;
}
在这种情况下,主线程id(LengthyOperation方法在其上运行)与此任务在其上运行的主线程id不同。长线程ID不应该与任务线程ID相同吗?您可以使用
TaskScheduler
样品
TaskScheduler scheduler = TaskScheduler.FromCurrentSynchronizationContext();
task.Start(scheduler); //use the schedular
结果
LENGTHY THREAD ID: 8
TASK THREAD ID: 8
其实很简单,不过你需要另一种方法
private async Task LongTaskImpl()
{
Debug.WriteLine("TASK THREAD ID: " + Thread.CurrentThread.ManagedThreadId);
for (int i = 0; i < 10000; i++)
{
File.ReadAllLines("abc.txt");
counter++;
}
}
static async Task LengthyOperation()
{
Console.WriteLine("Executing a lengthy operation...");
Debug.WriteLine("LENGTHY THREAD ID: " + Thread.CurrentThread.ManagedThreadId);
var task = LongTaskImpl();
await task;
}
专用异步任务LongTaskImpl()
{
WriteLine(“任务线程ID:+THREAD.CurrentThread.ManagedThreadId”);
对于(int i=0;i<10000;i++)
{
ReadAllLines(“abc.txt”);
计数器++;
}
}
静态异步任务长度操作()
{
WriteLine(“执行冗长的操作…”);
WriteLine(“冗长的线程ID:+THREAD.CurrentThread.ManagedThreadId”);
var task=LongTaskImpl();
等待任务;
}
现在,您有了一个任务,该任务与它的调用者在同一个线程上运行。
但是,您的代码中没有异步内容,因此它将同步运行。只是将某个内容转换为任务并不意味着它会神奇地变为异步,您必须为此调用(并等待)一些异步操作)
如何像HttpClient.GetStreamAsync()等异步方法那样异步启动任务
理想情况下,只有自然异步方法(如I/O)公开异步API。这通常通过Task.Factory.fromsync
或TaskCompletionSource
完成
例如:
静态任务MyOpAsync()
{
var tcs=new TaskCompletionSource();
…//建立一个回调,在操作完成时调用tcs.TrySetResult
返回tcs.Task;
}
如果希望它在同一个线程上运行,为什么要将其作为一项任务?为什么不把代码放在LengthyOperation方法中(或者作为常规方法调用调用内部内容)?让一个任务与调用者在同一个线程上执行有什么意义?我不明白:task
中的代码是完全同步的,你想在当前线程上运行它,那么,为什么要使用任务
s呢?如果希望LengthyOperation()
是异步的,那么这种异步必须来自某个地方:要么来自在另一个线程上运行代码,要么(更好)来自使用实际的异步操作,比如StreamReader.ReadToEndAsync()
(在文件上没有异步操作).@I3arnon如果任务中的代码包含一些await
s,那么在同一线程上执行同步部分通常是有意义的。@svick好的,这就是同步上下文的作用-确保等待继续在原始线程上执行。但对于任务本身来说,这真的毫无意义(除了一些奇怪的合作多任务场景)。为什么会投反对票?当然,这是个坏主意,但它确实回答了这个问题。@Luaan我的想法是一样的,OP被要求在调用线程上调用任务,以便两者都显示相同的ID。感谢您发布结果。不过我得自己试试:)这似乎是个好主意。我只是想试试,谢谢。事实上,我知道这是同步的。毕竟,这只是一个示例代码:)现在这正是我想要的。谢谢你,斯蒂芬!遗憾的是,我还没有足够的声誉,所以我不能对你的答案投赞成票。@好奇的是,如果这正是你一直在寻找的,那么你可以接受它。
static Task MyOpAsync()
{
var tcs = new TaskCompletionSource<object>();
... // Establish a callback that calls tcs.TrySetResult when the operation completes
return tcs.Task;
}