在我的代码中为什么QueueTasks()不能与main方法一起运行asyncronusly?是否有不同的方式来调用呢?
我希望QueueTasks(thingsToProcess, cts.Token);
启动异步方法,然后继续执行代码。
当我谷歌从非异步运行异步时,一切建议使用Task.Wait(),但我不想等,我只是想触发这个过程。我也谷歌搜索主线程异步,但发现了相互矛盾的建议,所以我不确定这里究竟是什么问题。我正在使用.net 4.5。
class Program
{
private static SemaphoreSlim maxThreads = new SemaphoreSlim(5);
private static readonly object syncLock = new object();
private static readonly Random getrandom = new Random();
private static int inQueue = 0;
public static int GetRandomNumber(int min, int max)
{
lock (syncLock)
{ // synchronize
return getrandom.Next(min, max);
}
}
static async Task DoSomething(string input, int row, SemaphoreSlim theSem)
{
theSem.Wait();
inQueue++;
int delay = GetRandomNumber(0, 5000);
await Task.Delay(delay);
Console.WriteLine(String.Format("{0}: Doing something to {1}", row,input));
inQueue--;
theSem.Release();
}
static async Task QueueTasks(List<string> things, CancellationToken ct)
{
int taskNumber = 0;
foreach (string thing in things)
{
if (ct.IsCancellationRequested)
{
Console.WriteLine("No more tasks being queued");
break;
}
else
{
maxThreads.Wait();
DoSomething(thing, ++taskNumber, maxThreads);
maxThreads.Release();
}
}
}
static void Main(string[] args)
{
// build list of 100 random strings to represent input
List<string> thingsToProcess = new List<string>();
for (int i = 0; i < 100; i++)
{
thingsToProcess.Add(Path.GetRandomFileName());
}
Console.WriteLine("Starting queue");
CancellationTokenSource cts = new CancellationTokenSource();
// I want this to initiate a queue starting but not stop the flow of code.
QueueTasks(thingsToProcess, cts.Token);
// This should run immediately after queue starts
Console.WriteLine("Hit X to stop current queue");
ConsoleKeyInfo cancel = Console.ReadKey();
while (cancel.KeyChar != 'x')
{
cancel = Console.ReadKey();
}
if (cancel.KeyChar == 'x')
{
cts.Cancel();
Console.WriteLine(String.Format("You requested a cancellation. {0} threads left to process", inQueue));
}
else
{
Console.WriteLine("Operation completed without interuption");
}
Console.ReadLine();
}
}
答案 0 :(得分:4)
async
不是一个神奇地使你的方法异步的关键字!它只允许您在其中使用await
关键字 - 您没有这样做。您的方法是完全同步的,因此在完成之前不会返回。
如果您在某个时候使用过await
,那么QueueTasks
将会返回,您可以继续执行Main
。
除此之外,你的代码非常不安全,所以你很幸运它实际上不运行多线程(实际上,它确实在多个线程上运行 - 但至少只有大约2-3个线程一个时间:) :)多线程的一个很好的启动是http://www.albahari.com/threading/。
您可以做的最简单的事情就是将QueueTasks
方法包装在Task.Run
中。这将使它在与被调用者平行的新线程上运行。
第二个最简单的方法是在{等待'信号量时使用await
内的QueueTasks
- await maxThreads.WaitAsync()
而不是maxThreads.Wait
。请注意,您应该删除DoSomething
内部的等待 - 您正在丢弃信号量插槽;实际上很可能像这样使你的代码陷入僵局(外部Wait
占用了所有五个插槽,这将阻止Wait
中的DoSomething
永久解锁。
最难的是实际学习如何使用并行执行和限制来正确处理生产者 - 消费者队列。同样,http://www.albahari.com/threading/是一个伟大的首发:)