2015-10-04 37 views
2

我有以下方法:將數據傳入任務延續

private void GetHistoricalRawDataFromTextFiles(MessageHeader header, HistoricalRawDataFromTextFileSubscriptionDto dto) 
{ 
    var computeInstance = GetComputeInstance(dto.SubscriberId, dto.ComputeInstanceId); 
    var task = computeInstance.GetHistoricalRawDataFromTextFiles(dto, progress => SendProgress(header.Sender, progress)); 

    task.ContinueWith(myTask => 
    { 
     dto.TimeSeries = myTask.Result; 
     Messenger.SendTo(SubscriberId, header.Sender, MessageType.Reply, MessageTopic.HistoricalRawDataFromTextFiles, dto); 
    }); 
} 

方法computeInstance.GetHistoricalRawDataFromTextFiles返回Task<List<string>>,我的問題是

  • 這是否是通過headerdto到拉姆達的正確方法表達和任務延續。在外部方法被調用時,在lambda表達式和任務延續內捕獲headerdto實例值是很重要的。在上次調用的任務完成之前,可能會再次調用相同的方法。

回答

1

,所述報頭和DTO實例值被捕獲 lambda表達式和任務繼續在 外方法被調用的時間內是很重要的。

當使用lambda表達式,得到什麼關閉了是可變,而不是該變量的值

只要headerdto不是您在進行方法調用之前每次修改的全局變量,那麼您應該沒問題。如果他們全局變量,那麼你需要找到一種方法來爲它們中的每一個創建本地副本。如果它們是引用類型,則需要克隆它們,如果它們是值類型,則需要將它們複製到lambda內的局部變量。

+0

它們不是全局變量,因爲它們可以全局訪問,但是,每個外部消息調用都會改變'header'和'dto'。那麼,唯一的方法就是克隆它們,然後將克隆傳遞給lambda和任務? –

+0

不,如果它們不是全局可修改的,並且每次都傳遞一個新實例,那麼代碼沒問題。 –

+0

謝謝,這使得它更清晰,所以,這只是歸結爲我傳入了對'header'和'dto'值的新引用,是正確的嗎? –

1

我認爲你的問題歸結爲:「我的方法線程安全嗎?」

我不認爲它與你捕獲的變量有關。

你的方法不似乎訪問共享/全局源(靜態/全局變量或字段)。(否則你需要同步)

即使這種方法是由多個線程調用同時它仍然是線程安全的,每次調用GetHistoricalRawDataFromTextFiles將處理一個單獨的「領域」 - 這是因爲每個線程都有自己的堆棧。

所以,無論你是否使用捕獲變量(指同一內存位置) - 你仍然可以獲得獨特dtoheader每次迭代的境界。

因爲每次調用(即使是線程化的),我都沒有在這裏看到任何相同的共享內存位置問題 - 獲取它自己的空間。

再次。這假設你沒有使用任何全局狀態。

+0

你準確定義**全局變量**是什麼?甚至可以在同一個線程中短時間連續地調用外部方法'private void GetHistoricalRawDataFromTextFiles(MessageHeader header,HistoricalRawDataFromTextFileSubscriptionDto dto)'(每個方法都有不同的'header'和'dto'實例),並且這個想法是旋轉任務並且運行他們的延續,以「捕獲」當時傳入方法的'header'和'dto'。我想我擔心第二個方法調用會影響第一個方法調用期間啓動的任務及其延續。 –

+0

@MattWolf通過全局變量,我的意思是一個可以從函數外部訪問的變量。 [它不一定是靜態的](https://dotnetfiddle.net/uPdsKX) –