2014-09-10 102 views
1

我正致力於將使用線程的舊代碼替換爲基於.NET 4.5任務的系統。如何在沒有ByRef的情況下處理異步函數?

我有以下的我想轉換的子;

Public Function Delay(Milliseconds As Integer, ByRef Job As Job) As Boolean 
    For i As Integer = 1 To CInt(Milliseconds/100) 
     Thread.Sleep(100) 
     If Job.IsCancelled Then Return True 
    Next 
    Return False 
End Function 

作業類是我自己的,但重要的是它包含了被設置爲1,如果作業應取消的整數。所以,Delay函數允許我將線程休眠X毫秒,但是如果在此期間作業被取消,它將會停止休眠並返回True。

我不知道如何用Await Task.Delay做到這一點,這是我的嘗試;

Public Async Function Delay(Milliseconds As Integer, Job As Job) As Tasks.Task(Of Boolean) 
    For i As Integer = 1 To CInt(Milliseconds/100) 
     Await Tasks.Task.Delay(100) 
     If Job.IsCancelled Then Return True 
    Next 
    Return False 
    End Function 

我遇到的問題是,異步方法不允許我使用的ByRef,這意味着它將無法在作業已被取消檢測。另一個問題是,在try/catch/finally或者一個synclock裏面不能使用await。我的印象是,你可以編寫看起來像同步代碼的異步代碼。我如何解決這些問題?

回答

3

你實際上並沒有改變方法體中的Job變量,所以你不應該通過引用來傳遞它,你應該通過值傳遞它。

也就是說,除非Job實際上是一個可變的值類型,而不是引用類型,在這種情況下是你的問題,你應該在這裏不使用可變值類型修復它。

還值得注意的是,如果您希望使用對象來封裝異步操作的可能取消,您應該使用CancellationToken(以及隨附的CancellationTokenSource)。它將提供您需要的所有功能,特別值得注意的是,它將處理所有適當的同步,使您不會遇到從多個線程訪問它的任何問題。它也恰好是一個參考類型。

如果您接受CancellationToken,您還可以將它傳遞給Task.Delay,使其在取消令牌時完成,而不是強制您的方法等待,直到延遲結束爲return false

+0

感謝您提供有關CancellationToken的信息。我在剛剛回答之後按問題編輯,但我在舊代碼中使用新函數時也遇到問題。我不能在synclock部分使用它。有沒有辦法解決這個問題? – iguanaman 2014-09-10 19:39:24

+0

@iguanaman這是一個完全獨立的問題,與你目前所問的問題完全不同。你應該問一個關於它的新問題。您還應該包含您正在使用的特定代碼,因爲這非常相關。 – Servy 2014-09-10 19:41:27

1

確保將Job聲明爲Class,而不是Structure。這將允許它通過ByVal(默認值),並在您的代碼中完美工作,因爲它將是一個引用類型,並且在外部處理的突變將在您的方法中可見。

由於您在功能內部不更改Job,因此不應傳遞ByRef

相關問題