如何以异步方式处理非托管资源?

时间:2017-05-01 13:37:54

标签: c# asp.net multithreading asynchronous dispose

是否可以在不等待结果的情况下在新线程中调用非托管资源的dispose()? 我有一个使用2个非托管资源的异步函数。 (rdKafka制片人和主题)。经过一些测试和时间戳测量,我意识到他们的Dispose功能需要很长时间才能完成,所以我想在不同的线程中调用这些资源的dispose(),而不是“等待”他的结果。 意思是,我想尽快得到结果,让一些线程处理dispose()。

这是我的代码:

public async Task<bool> ProduceMessage(object someobject)
    {
        var result = true;
        using (var producer = new Producer(_kafkaOptions.Uri)) {
            using (var topic = producer.Topic(_kafkaOptions.Topic, topicConfig)) {
                var report = topic.Produce(someobject);
                await report.ContinueWith(task =>
                {
                    if (task.Status == TaskStatus.RanToCompletion) {
                        //if produce succeed and task completed, return true
                        _logger.LogDebug("Producer Succeed");
                        result = true;
                    } else {
                        HandleError(task);
                        result = false;
                    }
                });

3 个答案:

答案 0 :(得分:0)

不要将它们放在using声明中。相反,请执行try/finally阻止并在Task.Run(() => producer.Dispose);部分中调用finally等。假设它们从不抛出异常,您将不需要等待Dispose调用,但您可能应该进行单元测试。如果值得等待成功记录,那么值得等待处理调用。目标是能够并行执行大量这些ProduceMessage调用(然后将它们作为批处理等待)。

您的Dispose调用有可能正在执行磁盘或套接字刷新。您可能希望在关闭方案中等待它们。另一个选择是在Produce调用中执行套接字刷新。这样你的成功记录会更加真实。

答案 1 :(得分:0)

如果您不希望Dispose出现在调用者线程中,只需继续执行即可。唯一令人讨厌的部分是确保在producer.Topic(_kafkaOptions.Topic, topicConfig)抛出异常时处理主题。

private async Task<bool> DoProduce(Topic topic, object someObject)
{
    try
    {
        var report = await topic.Produce(someObject);
        _logger.LogDebug("Producer Succeed");
        return true;
    }
    catch (Exception ex)
    {
        HandleError(ex);
        return false;
    }
}

public Task<bool> ProduceAsync(object someObject)
{
    var producer = new Producer(_kafkaOptions.Uri);

    Topic topic = null;

    try
    {
        topic = producer.Topic(_kafkaOptions.Topic, topicConfig);
    }
    finally
    {
        producer.Dispose();                
    }

    var task = DoProduce(topic, someObject);

    task.ContinueWith(t =>
    {
        topic.Dispose();
        producer.Dispose();
    }, TaskScheduler.Default);

    return task;
}

答案 2 :(得分:-1)

如果你想要的是控制资源的处理,我觉得你应该把资源注入到方法中。

这将负责[创建它们]并将它们从方法中移除并允许它及时完成。然后,您可以决定如何单独销毁资源。