Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.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# BackgroundWorker阻塞问题-集成测试和Real App之间不一致_C#_Backgroundworker - Fatal编程技术网

C# BackgroundWorker阻塞问题-集成测试和Real App之间不一致

C# BackgroundWorker阻塞问题-集成测试和Real App之间不一致,c#,backgroundworker,C#,Backgroundworker,我遇到了一个奇怪的情况。我试图使用BackgroundWorker实例的列表,对它们调用RunWorkerAsync(),然后等待所有实例完成,然后将响应返回给调用方。当我从一个NUnit集成测试调用该方法时,它工作得很好,该测试运行workers中的所有代码。然而,当我从我的web应用程序执行时,同样的代码不断阻塞主线程,RunWorkerCompleted回调永远不会触发。为什么会这样?这是我的代码(这里仅使用1个BackgroundWorker来说明,但我仅在实际中大于1时使用此代码):

我遇到了一个奇怪的情况。我试图使用BackgroundWorker实例的列表,对它们调用RunWorkerAsync(),然后等待所有实例完成,然后将响应返回给调用方。当我从一个NUnit集成测试调用该方法时,它工作得很好,该测试运行workers中的所有代码。然而,当我从我的web应用程序执行时,同样的代码不断阻塞主线程,RunWorkerCompleted回调永远不会触发。为什么会这样?这是我的代码(这里仅使用1个BackgroundWorker来说明,但我仅在实际中大于1时使用此代码):

向BackgroundWorkers发送消息并以阻塞方式执行它们的主代码:

// Build a list of BackgroundWorker instances representing the work needing to be done
var workers = new List<BackgroundWorker>
{
    GetContactsByFullNameAsync(lastName, firstName),
};

// Execute the work to be done (blocking during execution)
this.ExecuteAsyncWork(workers);

// Aggregate up the contacts and return the final result
return this.AggregateContacts(result);
//构建一个代表需要完成的工作的BackgroundWorker实例列表
var workers=新列表
{
GetContactsByFullNameAsync(lastName,firstName),
};
//执行要完成的工作(执行期间阻塞)
这是执行同步工作(工人);
//汇总联系人并返回最终结果
返回此.AggregateContacts(结果);
新建BackgroundWorker的专用函数(但不执行):

private BackgroundWorker GetContactsByFullNameAsync(字符串lastName,字符串firstName)
{
var worker=新的BackgroundWorker();
worker.DoWork+=(发送方,参数)=>
{
var result=new SuperSearchResultDTO();
IList contacts=_contactRepository.GetContactsByFullName(lastName,firstName);
//将任何生成的Contact实例转换为ContactDTO实例
if(contacts!=null&&contacts.Count!=0)
contacts.ToList().ForEach(c=>result.contacts.Add(ContactDTO.GetFromContact(c));
args.Result=结果;
};
worker.RunWorkerCompleted+=(发件人,e)=>
{
如果(例如错误!=null)
//在存储库中抛出了一个错误,但由于它是在单独的线程中抛出的,因此
//将不会停止当前线程按常规执行。我们需要使用记录异常
//结果,稍后再处理。扔在这里什么都没用。
_asyncWork[source]=new SuperSearchResultDTO{Exception=e.Error};
否则(如已取消)
_asyncWork[source]=new SuperSearchResultDTO{Exception=new Exception(“GetSSOContactsByMailAsync已取消”)};
其他的
//将结果从类型“object”强制转换为SuperSearchResultDTO
_asyncWork[source]=(超级搜索结果)e.Result;
};
返乡工人;
}
用于执行所有工作进程、阻止直到完成以及处理异常的私有方法:

private void ExecuteAsyncWork(List<BackgroundWorker> workers)
{
    // Kick of the searches against the different data sources simultaneously
    workers.ForEach(x => x.RunWorkerAsync());

    // BLOCK the current thread until either all the async methods are complete 
    while (workers.Any(x => x.IsBusy))
        System.Threading.Thread.Sleep(50);

    // Handle any exceptions
    var exception = _asyncWork.Where(x => x.Value != null && x.Value.Exception != null).Select(x => x.Value.Exception).FirstOrDefault();
    if (exception != null)
        throw exception;
}
private void executesyncwork(列出工作人员)
{
//同时对不同的数据源执行搜索
ForEach(x=>x.RunWorkerAsync());
//阻止当前线程,直到所有异步方法完成
while(workers.Any(x=>x.IsBusy))
系统.线程.线程.睡眠(50);
//处理任何异常
var exception=_asyncWork.Where(x=>x.Value!=null&&x.Value.exception!=null)。选择(x=>x.Value.exception)。FirstOrDefault();
if(异常!=null)
抛出异常;
}

您只是在主线程上调用
线程。Sleep
,因此它会阻塞。您需要使用回调或事件来解决此问题

private void ExecuteAsyncWork(List<BackgroundWorker> workers)
{
    // Kick of the searches against the different data sources simultaneously
    workers.ForEach(x => x.RunWorkerAsync());

    // BLOCK the current thread until either all the async methods are complete 
    while (workers.Any(x => x.IsBusy))
        System.Threading.Thread.Sleep(50);

    // Handle any exceptions
    var exception = _asyncWork.Where(x => x.Value != null && x.Value.Exception != null).Select(x => x.Value.Exception).FirstOrDefault();
    if (exception != null)
        throw exception;
}