2016-06-09 40 views
1

在我的C#Silverlight應用程序中初始化UI時,我對不同的服務進行了幾次異步調用。儘管異步執行所有加載的過程非常快捷,但仍然有時候需要加載的一些步驟發生在最後。跟蹤異步加載與線程安全嗎?

在過去的一些看法中,我實現了一個「加載列表」機制來幫助我跟蹤加載情況,並確保在他們觸發時任何操作的挑剔順序。這裏是一個非常簡化的例子:

private List<string> _loadingList = new List<string>(); 

// Called to begin the loading process 
public void LoadData(List<long> IDs){ 
    foreach(long id in IDs){ 
     DoSomethingToLoadTheID(id); 
     _loadingList.Add(id.ToString()); 
    } 
} 

// Called every time an ID finishes loading 
public void LoadTheIDCompleted(object sender, ServiceArgs e){ 
    UseTheLoadedData(e); 

    _loadingList.Remove(id.ToString()); 
    if(_loadingList.Count == 0) 
     LoadDataFinally(); 
} 

// Must be called after all other loading is completed 
public void LoadDataFinally(){ 
    ImportantFinishingTouches(); 
} 

這個東西適用於我的目的,我還沒有遇到任何問題。但我沒有信心我的線程安全的知識,我想是的,所以我想問幾個問題:

  • 有什麼辦法這種事情可以搞砸災難性的?
  • 有沒有更好的方法來完成相同的功能?

(我使用Visual Studio 2013和.NET Framework 4.5.51209,和Silverlight 5.0)

回答

1

有什麼辦法這種事情可以搞砸災難性的?

取決於你在做什麼,絕對。首先,您從多個線程訪問List(of T)。您應該使用ConcurrentList<T>,因爲它是線程安全的。請記住,被多個線程訪問/修改的任何類(包括.NET框架組件)都必須是線程安全的。 MSDN指出哪些框架組件是和不是。

有沒有更好的方法來完成相同的功能?

我沒有看到你的代碼中使用了多線程的任何地方,但我認爲你正在試圖做的是:

  • 獲取ID列表
  • 運行一些長時間運行或CPU綁定的過程,每個ID
  • 從標識

取決於你與每個ID做什麼性質的列表中刪除ID,該方法可能不同。舉例來說,如果工作是CPU綁定的,那麼你可以使用任務/ TPL:

// Using TPL 
var ids = new List<int>() {1, 2, 3, 4}; 
Parallel.ForEach(ids, id => DoSomething(id)); // Invokes DoSomething on each ID in the list in parallel 

或者,如果你需要,事情執行的順序進行細粒度控制...

var ids = new List<int>() {1, 2, 3, 4}; 

TaskFactory factory = new TaskFactory(); 
List<Task> tasks = new List<Task>(); 

foreach (var id in ids) 
{ 
    tasks.Add(factory.StartNew(() => DoSomething(id))); // executes async and keeps track of the task in the list 
} 

Task.WaitAll(tasks.ToArray()); // waits till everything is done 

tasks.Clear(); 

foreach (var id in ids) 
{ 
    tasks.Add(factory.StartNew(() => DoSomethingElse(id))); // executes async and keeps track of the task in the list 
} 

Task.WaitAll(tasks.ToArray()); // Wait till all DoSomethingElse is done 

// etc. 

現在如果您正在進行的工作是IO界限(例如,在需要等待緩慢響應的情況下進行web服務調用),則應該查看Asynchronous Programming with async and await (C#)

有很多方法可以處理多線程,有時找出正確的方式是挑戰的一部分(異步/等待與任務與信號量與背景工作者對比等)。

+0

是的,我沒有把實際的線程東西放在我的例子中,因爲它非常笨重。該項目使用WCF服務,但不幸的是,我不知道除了通過調用生成的* ServiceName * Async()方法啓動它們以外,這些工作是如何實現的,並且您通過訂閱生成的* ServiceName *來獲得結果。Completed事件。儘管我希望使用TPL,但我不確定它將如何適應這種模式,這在所有應用程序中都是如此。 –

+0

我還有一個印象,Silverlight無法訪問System.Collections.Concurrent命名空間中的任何內容,並且據我所知,從谷歌搜索中可以看出,並不存在ConcurrentList 之類的東西。 –

+0

http://stackoverflow.com/questions/18396139/which-version-of-silverlight-supports-task-parallel-library – DVK