Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# &引用;“新线程”;和异步_C#_Multithreading_Asynchronous_Async Await - Fatal编程技术网

C# &引用;“新线程”;和异步

C# &引用;“新线程”;和异步,c#,multithreading,asynchronous,async-await,C#,Multithreading,Asynchronous,Async Await,我使用下面的代码做了一个模拟并发的示例: var threads = new Thread[200]; //starting threads logic for (int i = 0; i < 200; i++) { threads[i].Start(); } for (int i = 0; i < 200; i++) { threads[i].Join();

我使用下面的代码做了一个模拟并发的示例:

var threads = new Thread[200]; 
//starting threads logic
for (int i = 0; i < 200; i++)
         {
             threads[i].Start();
         }
         for (int i = 0; i < 200; i++)
         {
             threads[i].Join();
         } 
var threads=新线程[200];
//启动线程逻辑
对于(int i=0;i<200;i++)
{
线程[i].Start();
}
对于(int i=0;i<200;i++)
{
线程[i].Join();
} 
该代码应该向数据库中插入数千条记录,而且似乎工作得很好,因为线程几乎同时完成

但是,当我使用:

 var tasks = new List<Task<int>>();
        for (int i = 0; i < 200; i++)
        {
            tasks.Add(insert(i));
            //   await insert(i);
        }
        int[] result = await Task.WhenAll(tasks);
var tasks=newlist();
对于(int i=0;i<200;i++)
{
增加(插入(i));
//等待插入(i);
}
int[]结果=等待任务.WhenAll(任务);
完成同样的逻辑需要很多时间


有人能给我解释一下有什么区别吗?我认为
Await
应该创建线程。

在第一个示例中,您手动创建了线程。在第二秒内,您创建了任务。任务-可能-正在使用线程池,其中线程数量有限。因此,大多数任务都在队列中等待,而很少有任务在可用线程上并行执行。

如果需要复制原始的基于
线程的行为,可以使用
task.Factory.StartNew(…,TaskCreationOptions.longlunning)
来安排工作,然后通过
Task.WaitAll
阻塞,直到辅助任务完成。我不推荐这种方法,但就行为而言,这将非常接近您的代码以前的工作方式

下面将对may在您的场景中无法获得预期性能的原因进行更深入的分析:

解释,第1部分(
async
并不表示“在不同的线程上”)

async
关键字标记的方法不会神奇地异步运行。它们仅仅能够将等待的操作(它们本身可能异步运行,也可能不异步运行)组合成一个更大的单元(通常是
Task
Task

如果您的
insert
方法是
async
,则它仍然可能至少同步执行部分工作。第一条
wait
语句前面的所有代码都肯定是这种情况。这项工作将在“主”线程(调用
insert
的线程)上执行,这将是您的瓶颈或至少是其中的一部分,因为当您在紧循环中调用
insert
时,该部分代码的并行度将为1,无论您是否等待生成的任务

为了说明上述观点,请考虑下面的例子:

void Test()
{
    Debug.Print($"Kicking off async chain (thread {Thread.CurrentThread.ManagedThreadId}) - this is the main thread");
    OuterTask().Wait(); // Do not block on Tasks - educational purposes only.
}

async Task OuterTask()
{
    Debug.Print($"OuterTask before await (thread {Thread.CurrentThread.ManagedThreadId})");
    await InnerTask().ConfigureAwait(false);
    Debug.Print($"OuterTask after await (thread {Thread.CurrentThread.ManagedThreadId})");
}

async Task InnerTask()
{
    Debug.Print($"InnerTask before await (thread {Thread.CurrentThread.ManagedThreadId})");
    await Task.Delay(10).ConfigureAwait(false);
    Debug.Print($"InnerTask after await (thread {Thread.CurrentThread.ManagedThreadId}) - we are now on the thread pool");
}
这将产生以下输出:

Kicking off async chain (thread 6) - this is the main thread OuterTask before await (thread 6) InnerTask before await (thread 6) InnerTask after await (thread 8) - we are now on the thread pool OuterTask after await (thread 8) 现在使用
TaskCreationOptions.LongRunning

IEnumerable<Task> tasks = Enumerable
    .Range(0, 200)
    .Select(_ => Task.Factory.StartNew(
        () => Thread.Sleep(100), TaskCreationOptions.LongRunning
    ));

await Task.WhenAll(tasks); // Completes in under 130 milliseconds.
IEnumerable任务=可枚举
.范围(0,200)
.Select(=>Task.Factory.StartNew(
()=>Thread.Sleep(100),TaskCreationOptions.LongRunning
));
等待任务。当所有(任务);//在130毫秒内完成。

生成200个线程通常不是一个好主意(这将不能很好地扩展),但是如果阻塞调用的大规模并行化是一个绝对要求,那么上面的代码片段向您展示了一种使用TPL的方法。

No.await不会创建线程。在此上下文中,“异步”一词与多线程无关。在代码中,您从何处启动任务?您是否知道启动线程会消耗超过1MB的内存?因此,200远远超过200MB。这是不做任何处理的。而且启动线程的速度很慢。从线程池中使用它们要好得多。谢谢大家,您的回复确实是有用的任务(wait/Async),它只是一个非常复杂的状态机。@Erik当然,但是任务是使用线程执行的。TaskSheduker管理任务,并使用线程池中的线程执行任务。谢谢各位,你们的回复真的很有帮助谢谢,你们的回复真的很有帮助
IEnumerable<Task> tasks = Enumerable
    .Range(0, 200)
    .Select(_ => Task.Factory.StartNew(
        () => Thread.Sleep(100), TaskCreationOptions.LongRunning
    ));

await Task.WhenAll(tasks); // Completes in under 130 milliseconds.