Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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_Asp.net Core_Async Await - Fatal编程技术网

C# 在自己的线程上执行的任务

C# 在自己的线程上执行的任务,c#,multithreading,asp.net-core,async-await,C#,Multithreading,Asp.net Core,Async Await,我有一个动作,去三个Cosmos数据库仓库检索信息。该操作具有以下代码: var task1 = _itemRepository.RetrieveByIdAsync(id); var task2 = _partsRepository.RetrieveForItemAsync(id); var task3 = _purchasesRepository.RetrieveForItemAsync(id, currentUserId); var userPurchased = await _userP

我有一个动作,去三个Cosmos数据库仓库检索信息。该操作具有以下代码:

var task1 = _itemRepository.RetrieveByIdAsync(id);
var task2 = _partsRepository.RetrieveForItemAsync(id);
var task3 = _purchasesRepository.RetrieveForItemAsync(id, currentUserId);

var userPurchased = await _userPurchaseRepository.HasUserPurchased(Session.UserId) // this is awaited because it is a SQL task and can only execute one at a time

await Task.WhenAll(task1, task2, task3);
调试时我注意到的是任务似乎在不同的线程上运行
System.Threading.Thread.CurrentThread.ManagedThreadId
与任务运行之前、每个任务以及等待任务之后不同

输入前的线程ID-5
项目存储库线程ID-61
零件存储库线程ID-5
采购存储库线程ID-60
WaitAll后的线程ID-6

存储库方法最终都会调用一个常见的QueryAsync方法,如下所示:

public async Task<IEnumerable<TDomainObject>> QueryAsync(Expression<Func<TDomainObject, bool>> predicate, FeedOptions options)
{
    var query = Client.CreateDocumentQuery<TDomainObject>(Collection.DocumentsLink, options).Where(predicate).AsDocumentQuery();

    List<TDomainObject> results = new List<TDomainObject>();
    while (query.HasMoreResults)
    {
        results.AddRange(await query.ExecuteNextAsync<TDomainObject>());
    }

    return results;
}
公共异步任务QueryAsync(表达式谓词,FeedOptions) { var query=Client.CreateDocumentQuery(Collection.DocumentsLink,options).Where(谓词).AsDocumentQuery(); 列表结果=新列表(); while(query.HasMoreResults) { AddRange(wait query.ExecuteNextAsync()); } 返回结果; } 我的理解是,使用async/await的所有处理都应该使用相同的请求线程,而且我担心我的代码可能没有达到预期的性能

我没有使用线程ID做任何事情,我只是想确保我没有创建不必要的线程


Edit:最初让我研究这一点的是,我发现
QueryAsync
方法中的调用堆栈,当在结果上断开指向时,调用堆栈是在存储库中启动的,而不是在控制器中启动的。

任务并行库和异步/等待功能的全部目的是将底层线程逻辑抽象出来。除非您的项目使用的框架具有在UI线程上运行的同步上下文(即:WinForms、WPF、Xamarin),您应该让框架来确定给定的
任务
是在当前线程上运行还是在其他线程上运行。

任务并行库和异步/等待功能的全部目的是将底层线程逻辑抽象出来。除非您的项目使用的框架具有在UI线程上运行的同步上下文(即:WinForms、WPF、Xamarin),否则您应该离开该框架来确定给定的
任务是在当前线程上运行还是在其他线程上运行。

ASP.NET dispatcher没有线程关联。在线程池线程处理的任何线程上继续执行完成通知都是一件好事,可以节省上下文切换的时间。只有在使用线程ID进行某些操作时,这才应该是一个问题。首先,这是个坏主意。如果您需要识别任务,那么应该通过在启动期间为其提供/检索的变量来完成。类似于一个简单的运行计数器(在检索/更新期间不要忘记竞争条件保护)。ASP.NET Core使用/管理线程池。启动请求时,它在一个线程上运行。当您等待异步I/O任务时,原始线程将返回到线程池,并可用于其他请求,直到操作完成,然后它将从线程池中选择另一个空闲/可用线程继续。它可能与原始线程相同,也可能不同(因为原始线程可能已被其他请求或继续使用)。除非您调用
Task.Run
TaskFactory.StartNew
(99%的情况下在web应用程序中不好)@Tseng不建议显式使用
ConfigureAwait(false)
,否则继续将请求相同的线程并可能导致错误delay@MrinalKamboj:是的,这是编写可重用库的推荐方法。在ASP.NET核心中,这不再是必需的,因为不再存在AspNetSynchronizationContext。事实上,ASP.NET核心放弃了在ASP.NET核心代码中使用
.ConfigureAwait(false)
。但在通用库(可用于桌面、UI、WPF或移动应用程序)中,仍然建议对每个等待的任务调用
.ConigureAwait(false)
。但是在纯ASP.NET核心库中(一个依赖于
Microsoft.AspNetCore.
libraries的程序,它不再是必需的ASP.NET dispatcher没有线程关联性。在线程池线程处理的任何线程上继续完成通知都是一件好事,可以节省上下文切换。只有在将线程ID用于.Wic时,这才应该是一个问题首先,h是一个坏主意。如果您需要识别一个任务,那么应该通过在启动期间提供给它/由它检索的变量来完成。类似于一个简单的运行计数器(在检索/更新期间不要忘记竞争条件保护).ASP.NET Core使用/管理线程池。当您启动请求时,它在一个线程上运行。当您等待异步I/O任务时,原始线程将返回到线程池并可用于其他请求,直到操作完成,然后它将从线程池中选择另一个可用线程继续。它可能是,也可能不是与原始线程相同(因为原始线程可能已被另一个请求或继续使用)。除非调用
任务,否则不会生成新线程。运行
TaskFactory。StartNew
(在99%的情况下,web应用程序不好)@Tseng是否建议使用
配置等待(false)
显式,否则继续将请求相同的线程,并可能导致delay@MrinalKamboj:是的,这是编写可重用库的推荐方法。在ASP.NET Core中,由于不再存在AspNetSynchronizationContext,因此不再需要这样做。事实上,ASP.NET Core已放弃使用
。ConfigureAwait(false)
在ASP.NET核心代码中。但在通用库中(可用于桌面、UI、WPF或移动应用程序