【发布时间】:2019-12-09 08:37:33
【问题描述】:
我不确定我是否在这里遗漏了什么,但更多的 for 循环似乎正在同步执行,即使我等待它之外的所有任务。
下面是我的代码:
static void Main(string[] args) {
var t = Start();
}
public static async Task < List < Task < TaskInfo >>> Start() {
var listOfTasks = new List < Task < TaskInfo >> ();
for (var i = 0; i <= 100; i++) {
var process = new Processor();
listOfTasks.Add(process.Process(i));
}
await Task.WhenAll(listOfTasks);
return listOfTasks;
}
我传入 taskId 以注销只是为了查看任务执行的顺序。
我在这里遗漏了一些非常明显的东西吗?
编辑:
根据下面的答案和 cmets 将代码更改为此,它仍然同步显示:
public class StartWork
{
public int TaskId { get; set; }
public Processor Processor { get;}
public StartWork()
{
Processor = new Processor();
}
}
static void Main(string[] args)
{
var t = Start();
}
public static async Task<TaskInfo[]> Start()
{
var tasks = new List<StartWork>();
for (int i = 1; i < 100; i++)
{
var work = new StartWork
{
TaskId = i
};
tasks.Add(work);
}
return await Task.WhenAll(tasks.Select(i => i.Processor.Process(i.TaskId)));
}
我在处理器类中调用的函数:
public Task<TaskInfo> Process(int taskId)
{
try
{
taskId = taskId + 1;
stopwatch.Start();
using (var bus = RabbitHutch.CreateBus(xxDev))
{
@event = new AutoResetEvent(false);
var replyTo = Guid.NewGuid().ToString();
var messageQueue = bus.Advanced.QueueDeclare(replyTo, autoDelete: true);
bus.Advanced.Consume(messageQueue, (payload, properties, info) =>
{
ReceivePdf(payload, properties, info);
return Task.FromResult(0);
});
taskInfo.InputFile = inputFile;
var html = File.ReadAllText(inputFile);
taskInfo.Html = html;
var message = PrepareMessage(new RenderRequest()
{
Html = Encoding.UTF8.GetBytes(html),
Options = new RenderRequestOptions()
{
PageSize = "A4",
ImageQuality = 70,
PageLoadRetryAttempts = 3
}
});
var correlation = Guid.NewGuid().ToString();
Console.WriteLine($"CorrelationId: {correlation}, TaskId {taskId}");
var props = new MessageProperties
{
CorrelationId = correlation,
ReplyTo = replyTo,
Expiration = "6000"
};
Publish(bus, props, message);
taskInfo.CorrelationId = Guid.Parse(correlation);
@event.WaitOne();
stopwatch.Stop();
taskInfo.TimeTaken = stopwatch.Elapsed;
return Task.FromResult(taskInfo);
}
}
catch (Exception e)
{
taskInfo.OutputFile = Empty;
return Task.FromResult(taskInfo);
}
}
void ReceivePdf(byte[] payload, MessageProperties properties, MessageReceivedInfo info)
{
var file = Format(outputFile, properties.CorrelationId);
taskInfo.OutputFile = file;
Console.WriteLine("Output written to " + file);
File.WriteAllBytes(file, payload);
var remaining = Interlocked.Decrement(ref outstandingRequests);
if (remaining == 0)
{
@event.Set();
}
}
【问题讨论】:
-
循环是同步的。循环添加到列表中的任务是异步的。
-
你必须
awaitStart并把Main设为async -
请解释为什么你认为它是同步的,你观察到的与你预期的不同(当然,还要解释你预期会发生什么)。你也可以在
process.Process中显示代码吗?如果该代码本质上不是异步的,那么您问题中的代码的作用并不重要。 -
@LasseV.Karlsen - 在控制台窗口中,它按顺序输出 taskId,例如 1,2,3,4,5,6 我希望顺序会有所不同,如果它是异步运行?
-
Process 方法中没有异步代码,这就是原因。即使您添加了任务和
async关键字,一切仍然是同步的。
标签: c# asynchronous async-await