【问题标题】:"Thread was being aborted." in test that tests code that fires a delegate on a background thread“威胁已经被清除了。”在测试中测试在后台线程上触发委托的代码
【发布时间】:2017-04-19 11:56:12
【问题描述】:

我有一些旧代码正在尝试为其编写测试。代码解析日志文件(在后台线程上),完成后触发传入的委托。

public delegate void finread(LogData l, LRParseState l, string e="");
void Thread_ParseLog(object info) {
  var info = ti as ThreadInfo;
  // some time later
  info.fin(log, state, error);
}
public static void ParseErrorLog(string log, finread fin){
    var pts = new ParameterizedThreadStart(Thread_ParseLog);
    new Thread(pts).Start(new ThreadInfo(log, fin));
}

代码是生产代码,一切正常并且已经运行了很长时间,但是当我尝试测试它时,我得到“线程被中止”。 Thread_ParseLog 方法中引发的异常。

测试看起来像这样:

void llt(string name, Action<LogData, LRParseState> test) {
    finread d = (LogData l, LRParseState s, string e) => {
      test(l, s);
    };
    LogReader.ParseErrorLog(name, d);
}
[TestMethod]
public void Create_LogReader_Big_Log() {
    llt(ERROR_LOG, (log, state) => {
        Assert.IsTrue(log != null); // never get here!
    });
}

测试数据比较大,大约55mb,正常处理大约需要500ms。

我也在输出窗口中遇到错误:

抛出异常:'System.Threading.ThreadAbortException' in mscorlib.dll System.AppDomainUnloadedException:试图访问 卸载 AppDomain。如果测试启动了一个线程,就会发生这种情况 但并没有阻止它。确保所有由 测试在完成前停止。

这似乎指向某种线程同步问题,但我对正在测试的代码无能为力。

显然,这是我编写测试的方式,我可以通过更改测试来修复它,但我不确定它为什么会发生。

TIA。

【问题讨论】:

  • 那么问题是什么?

标签: c# multithreading unit-testing


【解决方案1】:

使用诸如ManualResetEvent 之类的同步机制来等待测试的异步部分完成,然后再离开测试方法。

[TestMethod]
public void Create_LogReader_Big_Log() {
    // Use this event to wait until the asynchronous code has been executed 
    // before leaving the test method
    ManualResetEvent resetEvent = new ManualResetEvent(false);
    LogData logDataReceived = null;

    llt(ERROR_LOG, (log, state) => {
        logDataReceived = log;

        // Signal that the test has reached the end
        resetEvent.Set();
    });

    // Wait for the event to be set
    resetEvent.WaitOne();

    // Additionally wait for a grace period to allow the other thread to fully terminate
    Thread.Sleep(500);

    // Now perform the asserts on the received data
    Assert.IsTrue(logDataReceived != null);
}

【讨论】:

  • 从长远来看,应该更改实际代码以使用异步框架。然后,您还可以使测试方法异步,然后测试框架将能够直接测试异步方法。
  • 太好了,我的测试写得更干净,像这样: void llt(string name, Action test) { var mre = new ManualResetEvent(false); finread d = (LogData l, LRParseState s, string e) => { test(l, s); mre.set(); }; LogReader.ParseErrorLog(name, d); mre.WaitOne();并且根本不改变实际的测试代码。非常感谢。
【解决方案2】:

使用异步测试方法并稍稍延迟运行。

[TestMethod]
public async Task Create_LogReader_Big_Log()
{
    llt(ERROR_LOG, (log, state) => {
        Assert.IsTrue(log != null); // never get here!
    });
    await Task.Delay(3000);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    • 2012-10-29
    • 1970-01-01
    • 2021-09-24
    • 2022-01-17
    相关资源
    最近更新 更多