2012-01-31 55 views
1

在下面的代碼中,我想使用geometryService(由第三方提供的實用程序類)來順序計算幾個形狀區域。我失敗了,因爲第二次計算區域必須等到第一次計算完成。爲了解決這個問題,我可以將第二個面積計算放入完成計算事件處理程序中,但代碼很混亂。有沒有更好的方法可以讓geometryService.AreasAndLengthsAsync(secondShape)等待執行,直到geometryService.AreasAndLengthsAsync(firstShape)完成執行?如何讓代碼等待執行,直到其他事件處理程序完成?

Shape firstShape = new Shape(); 
Shape secondShape = new Shape(); 

GeometryService geometryService = new GeometryService(); 
geometryService.AreaAndLengthsCompleted += GeometryService_AreasAndLengthsCompleted; 
geometryService.AreasAndLengthsAsync(firstShape); 
geometryService.AreasAndLengthsAsync(secondShape); 

private void GeometryService_AreasAndLengthsCompleted(object sender, AreasAndLengthsEventArgs args){ } 
+0

如果有一個名爲'AreasAndLengthsAsync'的方法,我有一種直覺,那麼必須有它的同步對應'AreasAndLengths' :) – 2012-01-31 17:19:36

+1

API是否記錄在任何地方? – 2012-01-31 17:19:38

+1

http://help.arcgis.com/en/webapi/silverlight/1.2/apiref/topic1037.html – 2012-01-31 19:46:39

回答

1

可以使用的AutoResetEvent或ManualResetEvent的,簡單地定義一個在你的類的頂部,並調用等待中要等待其他事件的事件,然後調用設置在事件您在等待,等待將阻塞,直到Set被調用。

http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx http://msdn.microsoft.com/en-us/library/system.threading.manualresetevent.aspx

我想補充說,這並不理想,但你必須有序列化事件並且您依賴於第三方API,這可能是唯一的選擇。

6

您可以將每個ShapeQueue<Shape>

然後揭開序幕,第一計算,在完成處理程序檢查任何其他形狀的隊列中,如果有一個,處理它。

此外,您撥打的方法是AreasAndLengthsAsync()。通過轉換,大多數API設計人員將包含同名替代品,但不包含異步部分。因此,請查找AreasAndLengths()作爲替代方案。

+0

+1對於隊列的想法。不幸的是沒有AreasAndLengths()。有關文檔,請參閱http://help.arcgis.com/en/webapi/silverlight/1.2/apiref/topic1037.html。 – 2012-01-31 20:11:22

+0

您可以將Queue的想法和@emalamisura ManualResetEvent概念結合起來,給自己一個同步的方法調用,它會在返回之前處理隊列中的所有內容。 – 2012-01-31 22:15:36

2

這是異步方法的一個經典問題。如果你使用新的MS異步CTP,你可以相當乾淨地封裝一些這些東西,但是如果你使用傳統的東西被困住了,很難從這裏得到乾淨的代碼。

我採取的方法之一是用持續傳遞模式包裝事件處理程序模式。它不是很乾淨,但我更喜歡最終代碼的外觀。所以,你可以做這樣的事情:

public static void GetAreasAndLengthsAsync(Shape shape, Action<SomeResult> callback) 
{ 
    var geometryService = new GeometryService(); 
    geometryService.AreasAndLengthsCompleted += (s, e) => 
    { 
     if (callback != null) 
     { 
      callback(e.SomeResult); 
     } 
    }; 
    geometryService.AreasAndLengthsAsync(shape); 
} 

然後你就可以使用它像這樣:

GetAreasAndLengthsAsync(firstShape, firstShapeResult => 
{ 
    GetAreasAndLengthsAsync(secondShape, secondShapeResult => 
    { 
     DoSomethingWithTheseResults(firstShapeResult, secondShapeResult); 
    }); 
}); 

類似的東西,無論如何。格式很醜陋,但至少它表達了你的意圖。 (未編譯代碼,可能有錯誤。)

如果您不喜歡每次都重新創建geometryService,則可以在類中的字段級別執行此操作,然後將回調方法作爲大多數Async方法包含的UserState參數。

相關問題