C# 从非异步运行async(),无需等待

C# 从非异步运行async(),无需等待,c#,multithreading,asynchronous,C#,Multithreading,Asynchronous,在我的代码中,QueueTasks()为什么不异步运行到main方法?有没有一种不同的方式来调用Is,这样它就可以了 我想要QueueTasks(thingsToProcess,cts.Token)启动异步方法,然后继续执行代码 当我从非异步运行异步时,一切都建议使用Task.Wait(),但我不想等待,我只想触发进程。我也在谷歌上搜索了使主线程异步,但发现了相互矛盾的建议,所以我不确定这里的确切问题是什么。我正在使用.NET4.5 class Program { private sta

在我的代码中,QueueTasks()为什么不异步运行到main方法?有没有一种不同的方式来调用Is,这样它就可以了

我想要
QueueTasks(thingsToProcess,cts.Token)
启动异步方法,然后继续执行代码

当我从非异步运行异步时,一切都建议使用Task.Wait(),但我不想等待,我只想触发进程。我也在谷歌上搜索了使主线程异步,但发现了相互矛盾的建议,所以我不确定这里的确切问题是什么。我正在使用.NET4.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();
    }
}
类程序
{
私有静态信号量lim maxThreads=新信号量lim(5);
私有静态只读对象syncLock=新对象();
private static readonly Random getrandom=new Random();
私有静态int inQueue=0;
公共静态整数GetRandomNumber(整数最小值,整数最大值)
{
锁定(同步锁定)
{//同步
返回getrandom.Next(最小值、最大值);
}
}
静态异步任务DoSomething(字符串输入、int行、信号量lim-theSem)
{
theSem.Wait();
inQueue++;
int delay=GetRandomNumber(0,5000);
等待任务。延迟(延迟);
WriteLine(String.Format(“{0}:对{1}”、行、输入执行操作));
排队--;
释放;
}
静态异步任务队列任务(列出内容、取消令牌ct)
{
int taskNumber=0;
foreach(事物中的字符串)
{
如果(ct.IsCancellationRequested)
{
WriteLine(“不再有任务排队”);
打破
}
其他的
{
maxThreads.Wait();
DoSomething(thing、++taskNumber、maxThreads);
maxThreads.Release();
}
}
}
静态void Main(字符串[]参数)
{
//生成100个随机字符串的列表以表示输入
List thingsToProcess=new List();
对于(int i=0;i<100;i++)
{
thingsToProcess.Add(Path.GetRandomFileName());
}
Console.WriteLine(“起始队列”);
CancellationTokenSource cts=新的CancellationTokenSource();
//我希望它能够启动队列,但不会停止代码流。
QueueTasks(thingsToProcess,cts.Token);
//这应该在队列启动后立即运行
WriteLine(“点击X停止当前队列”);
ConsoleKeyInfo cancel=Console.ReadKey();
while(cancel.KeyChar!=“x”)
{
cancel=Console.ReadKey();
}
如果(cancel.KeyChar=='x')
{
cts.Cancel();
WriteLine(String.Format(“您请求了一个取消,剩下{0}个线程要处理”,inQueue));
}
其他的
{
Console.WriteLine(“操作完成,无中断”);
}
Console.ReadLine();
}
}

async
不是一个神奇地使您的方法异步的关键字!它只允许您在其中使用
wait
关键字,而您没有这样做。您的方法是完全同步的,因此在完成之前不会返回

如果您确实在某个时候使用了
wait
,这时
QueueTasks
将返回,您可以继续执行
Main

除此之外,您的代码是非常线程不安全的,所以您很幸运它实际上没有运行多线程(实际上,它确实运行在多个线程上,但至少一次只运行大约2-3个线程):)多线程的一个很好的开端是

您可以做的最简单的事情就是将
QueueTasks
方法包装在
Task.Run
中。这将导致它在与被调用方并行的新线程上运行

第二个最简单的方法是在“等待”信号量时在
QueueTasks
中使用
Wait
Wait maxThreads.WaitAsync()
而不是
maxThreads.Wait
。请注意,您应该删除
DoSomething
中的等待-您正在丢弃信号量插槽;实际上很有可能像这样死锁代码(所有五个插槽都被外部
Wait
占用,这将阻止
DoSomething
中的
Wait
解锁)


最困难的事情是实际学习如何通过并行执行和节流正确处理生产者-消费者队列。同样,它是一个很好的启动工具:)

async
不是一个神奇地使方法异步的关键字!它只允许您在其中使用
wait
关键字,而您没有这样做。您的方法是完全同步的,因此在完成之前不会返回

如果您确实在某个时候使用了
wait
,这时
QueueTasks
将返回,您可以继续执行
Main

除此之外,您的代码是非常线程不安全的,所以您很幸运它实际上没有运行多线程(实际上,它确实运行在多个线程上,但至少一次只运行大约2-3个线程):)多线程的一个很好的开端是

您可以做的最简单的事情就是将
QueueTasks
方法包装在
Task.Run
中。这将导致它在与被调用方并行的新线程上运行

第二个最简单的方法是在“等待”信号量时在
QueueTasks
中使用
Wait
Wait maxThreads.WaitAsync()
而不是
maxThreads.Wait
。请注意,您应该删除
DoSomething
中的等待-您正在丢弃信号量插槽;实际上,很可能会像这样死锁代码(所有五个插槽都被外部占用
Wait
,这将阻止