2012-01-05 26 views
9

Eşzamansız yürütme için bir geri arama argümanı alan bir yöntem var, ancak yakalama bloğu eşzamanlı çağrı tarafından atılan tüm özel durumları yakalamıyor gibi görünüyor (this.Submit, eşzamanlı bir yönteme başvuruyor) .Eşzamansız bir geri aramada atılan bir özel durumun yakalanması

public void Submit(FileInfo file, AnswerHandler callback) 
{ 
    SubmitFileDelegate submitDelegate = new SubmitFileDelegate(this.Submit); 
    submitDelegate.BeginInvoke(file, (IAsyncResult ar) => 
    { 
     string result = submitDelegate.EndInvoke(ar); 
     callback(result); 
    }, null); 
} 

Yeni iş parçacığı tarafından atılan özel durumun yakalanması ve özgün iş parçacığına gönderilmesinin bir yolu var mı? Ayrıca, bu, async istisnalarını ele almak için "uygun" bir yol mu?

try 
{ 
    target.Submit(file, (response) => 
    { 
     // do stuff 
    }); 
} 
catch (Exception ex) 
{ 
    // catch stuff 
} 

ama bunu yapmak için daha uygun ya da zarif bir yolu vardır: o (istisna sorun giderildikten varsayarak) böyle denilebilir yani benim kod yazdım?

+0

İlk kod örneğindeki catch bloğu, geri arama veya EndInvoke tarafından atılan bir istisna yakalayacaktır.İkinci kod örneğindeki catch bloğu SubmitFileDelegate yapıcısı veya BeginInvoke tarafından atılan herhangi bir özel durumu yakalayacaktır. Hangisini beklediğinizi yapmıyor/yapmasını istiyor? – dgvid

+0

Oops, bunu unuttu. İkincisinin düzgün çalışmasını istiyorum, ama şu anda da değil. – kevmo314

+0

"SubmitFileDelegate" in nasıl tanımlandığını gösterebilir misiniz? – GolfWolf

cevap

8

Bu 'en iyi uygulama' çözüm değil, ama çalışması gerekir basit bir mesaj olduğunu düşünüyorum: VUK içinde istisna işleme konusunda

fazla bilgi burada bulunabilir. Aslında yapar yöntem

public class SubmitFileResult 
{ 
    public string Result; 
    public Exception Exception; 
} 

Ardından:

yerine

private delegate string SubmitFileDelegate(FileInfo file); 

olarak tanımlanan temsilci sahip

private delegate SubmitFileResult SubmitFileDelegate(FileInfo file); 

olarak tanımlamak ve aşağıdaki gibi SubmitFileResult tanımlar dosya gönderimi (soruda gösterilmiyor) şu şekilde tanımlanmalıdır:

private static SubmitFileResult Submit(FileInfo file) 
{ 
    try 
    { 
     var submissionResult = ComplexSubmitFileMethod(); 

     return new SubmitFileResult { Result = submissionResult }; 
    } 
    catch (Exception ex) 
    { 
     return new SubmitFileResult {Exception = ex, Result = "ERROR"}; 
    } 
} 

Bu şekilde, sonuç nesnesini inceleyip, Sonuç veya Özel Durum alanı ayarlanmış olup olmadığına bakın ve buna göre davranın.

+0

Bu çağrı senkron değil mi? BeginInvoke geri aramada bir try/catch koymaya çalıştım (ve örneğinizle olsa da) ancak istisnayı yakalayamadı. – kevmo314

+0

Hayır, senkron değil. Lütfen iki 'Gönderme' yönteminin bulunduğunu unutmayın: Yukarıda anlattığım (bu 'SubmitFileDelegate' tanımlamasıyla eşleşmesi gereken) ve sorunda sunduğunuz kişi, 'BeginInvoke' diğerini (yani bir async çağrısıdır)). – GolfWolf

3

Kısaca, hayır.

submitDelegate.BeginInvoke numaralı telefonu aradığınızda, yeni parçacığı oluşturur, döndürür ve try/catch bloğunuzdan hemen çıkar (yeni thread arka planda çalışırken).

Ancak, böyle tüm işlenmeyen özel durumları yakalamak olabilir: Bu, uygulama etki alanında ancak (yalnızca güvenlik zaman uyumsuz yöntemini) her şeyi yakalayacak

AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(YourException);

.

+0

Sonra istisnaları işlemek için tercih edilen bir yolu var mı? Ben geri aramalar JS dünyasından fonksiyon (err, sonuç) {} gibi bir şey olsaydı, ama C# kod örneklerinde böyle bir şey görmedim. C# ile yapılması gerekiyordu ...: S – kevmo314

+0

@ w0lf'ın cevabı temel olarak şu; Yanıt tipinizde gerçekleşen istisnayı tamamlar ve tamamlandıktan sonra dışarı çekersiniz. –

9

.NET 4.0'ı hedefliyorsanız, yeni Görev Paralel Kitaplığı'nı kullanabilir ve Task nesnesinin Exception özelliğini gözlemleyebilirsiniz.

public Task Submit(FileInfo file) 
{ 
    return Task.Factory.StartNew(() => DoSomething(file)); 
} 

private void DoSomething(FileInfo file) 
{ 
    throw new Exception(); 
} 

Sonra bu gibi kullanmak:

DoSomething
Submit(myFileInfo).ContinueWith(task => 
{ 
    // Check task.Exception for any exceptions. 

    // Do stuff with task.Result 
}); 

zaman uyumsuz çağrı istiyorum yöntemdir ve ContinueWith geçmek temsilci geri aranıyorsunuz. http://msdn.microsoft.com/en-us/library/dd997415.aspx

İlgili konular