2017-05-01 2 views
-1

Ist es möglich, dispose() von nicht verwalteten Ressourcen in einem neuen Thread aufzurufen, ohne auf das Ergebnis zu warten? Ich habe eine asynchrone Funktion, die 2 nicht verwaltete Ressourcen verwendet. (rdKafka Produzent und Thema). Nach einigen Tests und der Zeitstempelmessung wurde mir klar, dass die Dispose-Funktion eine lange Zeit braucht, um fertig zu werden. Daher möchte ich die dispose() dieser Ressourcen in einem anderen Thread aufrufen und nicht auf sein Ergebnis "warten". Bedeutung, ich möchte das Ergebnis so schnell wie möglich bekommen und lassen einige Thread behandeln die dispose() wann immer.Wie können nicht verwaltete Ressourcen asynchron verteilt werden?

Hier ist mein Code:

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

Nicht direkt auf Ihre Frage bezogen, aber Sie sollten nie async/await mit 'ContinueWith' mischen, es führt zu vielen Fehlern. [Sie sollten nur 'erwarten Bericht 'und haben den Code in' ContinueWith 'sein danach] (https://gist.github.com/leftler/2767460d2aa135aa80c9b123e517b51b). Auch bitte aktualisieren Sie Ihre Frage, um den Rest der Methode zu zeigen, es hilft uns, Antworten zu bilden. –

+0

Entschuldigung, ich bin neu hier :) danke für den Kommentar – Shani

Antwort

0

Sie sie nicht in einer using Anweisung setzen. Stattdessen, machen Sie einen try/finally Block und rufen Sie Task.Run(() => producer.Dispose); usw. im finally Teil auf. Sie müssen nicht auf die Dispose Anrufe warten, vorausgesetzt, dass sie nie eine Ausnahme werfen, aber Sie sollten wahrscheinlich für Unit-Testzwecke. Wenn es sich lohnt, auf die Erfolgsprotokollierung zu warten, lohnt es sich auch, auf die Entsorgungsaufrufe zu warten. Das Ziel ist, in der Lage zu sein, viele dieser Anrufe parallel zu erledigen (und dann als Batch zu warten).

Es besteht die Möglichkeit, dass Ihre Dispose Anrufe eine Festplatte oder Socket Flush machen. Möglicherweise möchten Sie in einem Shutdown-Szenario auf sie warten. Eine andere Option wäre, den Socket-Flush im Produce-Aufruf auszuführen. Auf diese Weise würde Ihre Erfolgsprotokollierung wahrheitsgemäßer sein.

-1

Wenn was Sie wollen, ist die Kontrolle über die Entsorgung von Ressourcen, Es klingt für mich, als ob Sie die Ressourcen in die Methode injizieren sollten.

Das würde die Verantwortung dafür übernehmen, sie von der Methode wegzubringen und sie zeitnah fertig zu stellen. Sie können dann entscheiden, wie Sie die Ressourcen separat zerstören.

+0

Wenn Sie etwas ablehnen, ist die höfliche Sache, einen Kommentar zu machen, warum Sie fühlen, dass etwas nicht eine gute Idee ist, so dass jeder davon profitieren kann und Chip in. – JuanR

+0

Sie wurden wahrscheinlich downvoted, weil dies die Frage nicht beantwortet. Dies ist ein Kommentar und sollte als eins gepostet werden. (Ich bin übrigens nicht der Downvoter). –

+0

Danke @ChrisDunaway, obwohl ich respektvoll nicht zustimmen. Es ist eine Lösung, die das Problem lösen würde. Ich kann die Lösung bei Bedarf erweitern. Davon abgesehen sollte sich der Abenteurer die Zeit nehmen, sich zu äußern, um zu vermeiden, dass die Leute ihre Zeit verschwenden müssen, um herauszufinden, warum er/sie das getan hat. – JuanR

0

Wenn Sie nicht möchten, dass Dispose im aufrufenden Thread auftritt, führen Sie es einfach in einer Fortsetzung aus. Der einzige nervige Teil ist sicherzustellen, dass das Thema entfernt wird, wenn producer.Topic(_kafkaOptions.Topic, topicConfig) eine Ausnahme auslöst.

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; 
} 
Verwandte Themen