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
Multithreading 如何编写MSTest单元测试来侦听从另一个线程引发的事件?_Multithreading_Unit Testing_Mstest - Fatal编程技术网

Multithreading 如何编写MSTest单元测试来侦听从另一个线程引发的事件?

Multithreading 如何编写MSTest单元测试来侦听从另一个线程引发的事件?,multithreading,unit-testing,mstest,Multithreading,Unit Testing,Mstest,我正在编写一个测试,希望从它正在调用的对象接收事件。具体来说,我调用一个对象,该对象通过SSH(使用开源Granados项目)连接到AIX机器,然后断开连接,我希望确保收到断开连接期间引发的OnConnectionClosed事件。这听起来很简单,我在过去写过很多类似的测试,但这次发生了一些奇怪的行为,我相信这与线程有关 基本上,我调用的对象在不同的线程上引发“OnConnectionClosed”事件,而不是我从中调用它。我看到的是,当我通过从UI中选择“调试测试”来运行测试时,它通过了,但如

我正在编写一个测试,希望从它正在调用的对象接收事件。具体来说,我调用一个对象,该对象通过SSH(使用开源Granados项目)连接到AIX机器,然后断开连接,我希望确保收到断开连接期间引发的OnConnectionClosed事件。这听起来很简单,我在过去写过很多类似的测试,但这次发生了一些奇怪的行为,我相信这与线程有关

基本上,我调用的对象在不同的线程上引发“OnConnectionClosed”事件,而不是我从中调用它。我看到的是,当我通过从UI中选择“调试测试”来运行测试时,它通过了,但如果我选择“运行测试”,它将失败(即使在调试运行期间没有设置断点)。我在谷歌上搜索了一下,发现这似乎表明默认情况下MSTest主机以单线程模式运行,但配置更改可以使其以多线程模式运行。这听起来似乎可以从逻辑上解决我的问题,但当然,它没有

我遇到的其他一些帖子也让我觉得MSTest根本没有监视后台线程(因此它们引发的事件没有被“听到”)。这也是有道理的,因为它似乎是在调试模式下工作的,而且上面的修复程序似乎应该在逻辑上解决这个问题,那么我不明白为什么它不工作。有可能我只是没有正确地处理线程,尽管如果是这样的话,我认为在调试模式下这仍然是一个问题

有没有其他人尝试过以类似的方式测试某些东西?如果是,您是否遇到过类似的问题?如果是,你是如何解决的

我在下面粘贴了相关的单元测试代码(出于安全原因,我删除了连接信息)

[TestClass]
公共类SSHReaderTests
{
接收到的私有布尔=假;
私有委托bool SimpleFunc();
[测试初始化]
公共无效MyTestInitialize()
{
接收=假;
}
[测试方法]
public void应在成功连接断开连接后引发ReaderConnectionClosed事件
{
IReader reader=new SSHReader();
reader.OnReaderConnectionClosed+=委托
{
接收=真;
};
reader.Connect(“****”、“****”、“****”);
//Assert.IsTrue(reader.IsConnected);
reader.Disconnect();
//Assert.IsFalse(reader.IsConnected);
Assert.IsTrue(WaitUntilTrue(委托{
收到报税表;},30000,1000);
}
私有静态bool WaitUntilTrue(SimpleFunc func,int timeoutInMillis,int timebetween checksinmillis)
{
秒表秒表=新秒表();
秒表。开始();
while(stopwatch.elapsedmillisons
使用System.Threading命名空间中的WaitHandle类。自动重置事件或手动重置事件。两者之间的区别在于,AutoResetEvent允许一个线程在每次设置时继续,而ManualResetEvent则释放集合中所有等待的线程


示例不起作用的原因与编译器优化有关。代码实际上并没有按照您乍一看所想的方式编译。最可能的情况是,编译器将执行类似于将局部变量放入寄存器中的操作,而在检查的循环期间从未实际获取它。使用volatile关键字可以避免这种情况,但我强烈建议您阅读线程和并发方面的更多详细信息。Joe Duffy在的博客是一个很好的入门资源,我强烈推荐他即将出版的《Windows上的并发编程》一书。

这不完全是你想要的,但是你可以通过查看MS研究项目找到一些可行的解决方案或至少是想法。它用于.net中的多线程并发测试

[TestClass]
public class SSHReaderTests
{
    private bool received = false;
    private delegate bool SimpleFunc();

    [TestInitialize]
    public void MyTestInitialize()
    {
        received = false;
    }

    [TestMethod]
    public void Should_raise_OnReaderConnectionClosed_event_after_successful_connection_is_disconnected()
    {
        IReader reader = new SSHReader();

        reader.OnReaderConnectionClosed += delegate
                                     {
                                         received = true;
                                     };

        reader.Connect("*****", "*****", "*****");

        //Assert.IsTrue(reader.IsConnected);

        reader.Disconnect();

        //Assert.IsFalse(reader.IsConnected);

        Assert.IsTrue(WaitUntilTrue(delegate {
            return received; }, 30000, 1000));
    }

    private static bool WaitUntilTrue(SimpleFunc func, int timeoutInMillis, int timeBetweenChecksInMillis)
    {
        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();

        while(stopwatch.ElapsedMilliseconds < timeoutInMillis)
        {
            if (func())
                return true;

            Thread.Sleep(timeBetweenChecksInMillis);
        }
        return false;
    }
}