我不确定我是否在这里丢失了一些东西,但是更多的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登出只是为了查看任务执行的顺序。
我在这里真的缺少明显的东西吗?
编辑:
已根据下面的答案和注释将代码更改为该代码,但仍会同步出现:
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();
}
}
答案 0 :(得分:1)
这是一个同步任务
listOfTasks.Add(process.Process(i));
您只是将项目添加到列表中。
这也是同步任务
process.Process(i);
上面的函数返回的任务是异步的,它将在代码的whenAll调用中异步执行。
请记住,当所有人都将等待所有任务运行时,并且如果任务很琐碎,则由于它们一个接一个地启动,因此大多数情况下会偶然运行。
如果执行的任务代码根据输入的执行时间而有所不同,您会看到一些区别。
答案 1 :(得分:0)
第一个异步并不意味着多线程,异步用于运行后台任务而不阻塞UI或运行I / O操作而不会阻塞主线程。 通常,操作系统使用多线程处理异步,但是并不能保证。 如果您要确保启动多个线程,请使用Thread.Start。
无论如何,您都必须强制代码同步运行,因为您无需等待即可在Main方法中调用async方法start。
您需要将代码更改为:
static async void Main(string[] args)
{
var t = await Start();
}
或不等待(但程序有在任务完成前终止的风险):
static void Main(string[] args)
{
Task.Run(async () => {
var t = await Start();
});
}