0

请考虑以下简单代码,然后我会问我的问题。

public static void Save(XmlDocument saveBundle)
    {
        ThreadStart threadStart = delegate
        {
            SaveToDatabase(saveBundle);
        };

        new Thread(threadStart).Start();            
    }

在 Visual Studio (2005) 中使用线程的问题是你不能轻易地遍历它们(我相信有一种方法可以切换我没有研究过的线程,因为我希望有一种更简单的方法)。

所以,在现场,我的代码比上面的例子更复杂,我们使用一个新线程,因为它对时间很关键,但原理是一样的。最重要的是,测试的时间并不紧迫!

目前,我可能会做类似使用的事情,#if debug但这样做感觉不对 - 我在这里以正确的方式使用 #if 还是有更好的方法来解决这个问题?

public static void Save(XmlDocument saveBundle)
    {

   #if debug
      {
        SaveToDatabase(parameters);
        }
   #else
        {
            ThreadStart threadStart = delegate
            {
                SaveToDatabase(parameters);
            };

            new Thread(threadStart).Start();
        }
   #endif
      }
    }

虽然我被困在 .NET 2.0 上,但我对 .NET 20 以后的任何版本都感兴趣(我相信有一天我会离开侏罗纪并加入其他人的行列)

4

3 回答 3

2

我会说您的原始代码缺少一个重要功能;操作完成(或失败)时的某种报告机制:

public static void Save(XmlDocument saveBundle, Action<Exception> completedCallback)
{
    ThreadStart threadStart = delegate
    {
        try
        {            
            SaveToDatabase(saveBundle);
            completedCallback(null);
        }
        catch (Exception ex)
        {
            completedCallback(ex);
        }
    };

    new Thread(threadStart).Start();            
}

这样,您可以使用某种同步方法来编排您的单元测试:

Exception actualException = null;
using (AutoResetEvent waitHandle = new AutoResetEvent(false))
{

    instance.Save(xmlDocument, ex =>
    {
        actualException = ex;
        waitHandle.Set();
    });
    waitHandle.WaitOne();
}

Assert.IsNull(actualException);
于 2012-12-14T08:59:16.537 回答
1

如果您真正想做的不是在调试版本中使用线程 - 这是正确的方法,也可能是最快和最有能力的方法。它可能看起来有点难看,但替代方案只是更多的布尔、配置和其他变通方法。

如果您有兴趣直接调试线程(如果并发是一个问题,这可能很重要!您应该始终尽可能靠近生产环境进行测试),那么您可以简单地去 (Debug -> Windows -> Threads) 然后右键单击要调试的线程并“切换到线程”。

于 2012-12-14T08:59:59.220 回答
0

也许您可以将此线程代码放入单独的方法中,并在测试时替换该方法。

virtual void SaveToDBInSeparateThread(...)
{
    ThreadStart threadStart = delegate
    {
        ...
    };

    new Thread(threadStart).Start();  
}

然后,您可以代替返回 void 返回线程运行或类似的东西。

或者您可以向您的方法添加一个输入参数,如下所示:

virtual void SaveToDB(bool inSeparateThread)
{
    if(inSeparateThread)
    {
      ThreadStart threadStart = delegate
      {
        ...
      };

      new Thread(threadStart).Start();  
    }
    ...
}

或者您可以提供某种 DatabaseSavingContext:

interface IDBSaveContext
{
    public void SaveToDB(...)
}

并根据执行类型使用此接口的不同实现(线程、非线程)。

于 2012-12-14T09:06:32.560 回答