【问题标题】:Unit test is running forever with Tasks单元测试通过任务永远运行
【发布时间】:2016-03-24 00:17:34
【问题描述】:

我有一个永远运行的单元测试:

[Test]
public bool test()
{
    manager.Send(10);

    Thread.Sleep(1000);

    manager.Messages.Should().HaveCount(10);

    return true;
}

manager.Send() 方法是:

private void Send()
{
    try
    {
        var entities = GetAllEntities();

        foreach (var group in entities.GroupBy(r => r.Priority))
        {
            var tasks = group.Select(entity => Task.Factory.StartNew(() => manager.SendEntity(entity))).ToList();
            Task.WaitAll(tasks.ToArray());

            if (tasks.All(r => r.Result.Result == true))
            {
                // some code here...
            }
        }
    }
    catch (Exception e)
    {
        logger.FatalException(e.Message, e);
    }
    finally
    {
        logger.Info("End...");
    }
}

和 SendEntity() 方法:

public Task<bool> SendEntity(DeferredEntity entity)
{
    var taskCompletionSource = new TaskCompletionSource<bool>();

    try
    {
        logger.Info("Sending entity {0} with params: {1}", entity.Entity, GetEntityParams(entity));

        server.SendToServer(entity, (response, result) =>
        {
            taskCompletionSource.SetResult(result);
        });
    }
    catch (Exception e)
    {
        logger.FatalException(e.Message, e);
    }

    return taskCompletionSource.Task;
}

在单元测试管理器中。Send(10) 永远运行。我调试了代码,发现问题出在

if (tasks.All(r => r.Result.Result == true))

调试器在这条线上停止并永远休眠。我做错了什么?我将单元测试方法的返回值添加到 bool (异步方法不会在 void 方法中引发异常)。但这无济于事。你有什么建议吗?

【问题讨论】:

    标签: c# unit-testing


    【解决方案1】:

    你会陷入僵局。 首先,您不必使用

    启动新线程
    Task.Factory.StartNew(() => manager.SendEntity(entity)
    

    看来SendToServer 已经是异步的了。

    使用Task.Wait***/Task.Result 也是一种不好的做法,请使用异步流

    private async Task Send()
    {
        try
        {
            var entities = GetAllEntities();
    
            foreach (var group in entities.GroupBy(r => r.Priority))
            {
                var tasks = group
                    .Select(entity => manager.SendEntity(entity))
                    .ToArray();
    
                var results = await Task.WhenAll(tasks);
                if (results.All(result => result))
                {
                    // some code here...
                }
            }
        }
        catch (Exception e)
        {
            logger.FatalException(e.Message, e);
        }
        finally
        {
            logger.Info("End...");
        }
    }
    

    但是如果你不想重写发送方法你可以使用.ConfigureAwait(false)

    return taskCompletionSource.Task.ConfigureAwait(false);
    

    但无论如何,删除StartNew - 你不需要这个。

    【讨论】:

    猜你喜欢
    • 2018-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-30
    • 2022-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多