Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.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# nUnit断言。委托并发性问题_C#_Multithreading_Asynchronous_Nunit_Task Parallel Library - Fatal编程技术网

C# nUnit断言。委托并发性问题

C# nUnit断言。委托并发性问题,c#,multithreading,asynchronous,nunit,task-parallel-library,C#,Multithreading,Asynchronous,Nunit,Task Parallel Library,我在代码中遇到了一些暂时的死锁,我无法控制它 简单代码(我无法创建简单的调用链来重现InvokeChangeEvent中的代码) 我知道你们都(:D)想要可执行代码,但我无法将其切分,因此我希望通过解释获得一些见解 发生的情况:sut.InvokeChangeEvent调用一个事件处理程序,该事件处理程序随后调用一个async事件处理程序,该事件处理程序随后调用一些async。链的末尾会产生一个任务。运行,它最终会写入3个文件 上面的断言被实现为一个在之后带有的委托,该委托返回一个Delayed

我在代码中遇到了一些暂时的死锁,我无法控制它

简单代码(我无法创建简单的调用链来重现
InvokeChangeEvent
中的代码)

我知道你们都(:D)想要可执行代码,但我无法将其切分,因此我希望通过解释获得一些见解

发生的情况:
sut.InvokeChangeEvent
调用一个事件处理程序,该事件处理程序随后调用一个
async
事件处理程序,该事件处理程序随后调用一些
async
。链的末尾会产生一个
任务。运行
,它最终会写入3个文件

上面的断言被实现为一个在
之后带有
的委托,该委托返回一个
DelayedConstraint
,并且具有非常大的最大时间(15秒)和很小的轮询间隔

现在,当我调试代码时,InvokeChangeEvent调用将完全执行到最后一个Task.Run,但当Task.Run返回时,执行将返回到主线程,并在输入“wait with polling”时执行断言

然而,断言永远不会成功。当我调试问题时,Task.Run的返回总是在断言委托运行(并且失败)之后处理

我发现,当我放置
等待任务时,延迟(3000)
正如前面提到的,测试中的系统有很多等待和任务。运行被链接,我无法用一些简单的可运行代码重现这个问题

我在谷歌上搜索了一段时间,我不明白为什么Task.Run(在另一个线程上执行)会出现(临时)死锁,即使
DelayedConstraint
有一个明确的轮询间隔来允许主线程进行

它看起来像是
DelayedConstraint
通过某种
thread.Sleep
锁定主线程<代码>等待任务。延迟
没有,我知道这一点。让我困惑的是,我检查过我是否总是执行
wait
(并且从不执行
Task.Result
,等等),因此我希望在执行断言之前已经写入文件

(注意:
Thread.Sleep
而不是
wait Task.Delay
不起作用。)

通常,
DelayedConstraint
用于确保文件系统正确地写入了所有文件,因为我遇到了文件系统处理文件的一些延迟

我觉得
async void
事件处理程序可能会造成我不理解的情况


如果我成功创建了一个简单的示例,我将更新线程。

与VS2012单元测试类似,尝试
async Task
签名,而不是
async void
测试方法。这样,NUnit应该能够跟踪挂起的任务状态,并通过
task.Exception
检查异常


根据定义,
async void
方法是一个fire-and-forget概念。该方法立即返回(准确地说,在它内部的第一个异步
wait
),然后无法处理它的完成或它内部可能抛出的任何错误。按原样,
async void
方法,如果异常在方法中通过
try/catch

处理,那么您是否尝试过
public async Task Test()
而不是
public async void Test()
?@nosratio感谢您的提示,我将尽快对其进行测试。我不知道nUnit支持异步任务。我很幸运,他们扩展了测试以支持异步。虽然我这里没有代码,但我想知道这是否会编译,因为我没有在上面的代码中返回任务。Samuel,实际上我不确定NUnit是否支持异步方法,但是
task
void
的几率更高。VS2012+单元测试就是这样。如果NUnit不支持它,也许您仍然可以在NUnit包装器中返回一个
Task
并执行
Task.Wait()。由于NUnit似乎支持异步任务,所以我将所有异步空都转换为它,以避免此类暂停。如果你回答你的评论,我会把它标记为回答。
[Test]
public async void Test()
{
    sut.InvokeChangeEvent("./foo.file");
    // Event is handled by an async handler chaining multiple await resulting in a file write

    // await Task.Delay(3000);

    Assert.That(() => Directory.GetFiles("some dir").Count(), Is.EqualTo(3).After(15000, 300));

}