2017-05-01 75 views
-1

是否可以在不等待结果的情况下在新线程中调用非托管资源的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; 
        } 
       }); 
+2

与您的问题没有直接关系,但是您不应该将异步/等待与'ContinueWith'混合使用,否则会导致很多错误。 [你应该只是'等待报告',并在'ContinueWith'后面的代码](https://gist.github.com/leftler/2767460d2aa135aa80c9b123e517b51b)。还请更新您的问题以显示该方法的其余部分,它将帮助我们形成答案。 –

+0

对不起,我是新来的:)感谢您的评论 – Shani

回答

0

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

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

-1

如果你想要的是控制资源的处置,这听起来像你应该注入资源的方法。

这将负责[创建它们并]将它们从方法中分离出来,并让它们及时完成。然后,您可以决定如何分开销毁资源。

+0

如果你打算下决心,有礼貌的事情是做出评论,为什么你觉得不是一个好主意,让每个人都可以受益并芯片英寸 – JuanR

+0

您可能downvoted,因为这不能回答这个问题。这是一条评论,应该作为一个发布。 (顺便说一下,我不是downvoter)。 –

+0

谢谢@ChrisDunaway,虽然我很不以为然。这是解决问题的解决方案。如果需要,我当然可以扩展解决方案。话虽如此,但下决心还是应该花点时间评论一下,以避免人们不得不浪费时间来弄清楚他/她为什么这样做。 – JuanR

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; 
} 
相关问题