2013-07-05 41 views
1

我很抱歉發佈這樣的noob問題,但我找不到答案。我不擅長單元測試,所以我不確定這一點。這是返回一個線程安全的字節[]的最佳方式嗎?也可以在這裏初始化數組並在另一個線程中修改它?如何返回線程安全字節[]?

public async Task<byte[]> GetData() 
{ 
    var _buffer = new byte[1024]; 
    try { await Task.Run(() => ModifyArray(_buffer)); } 
    catch { return null;} 

    return _buffer.ToArray(); 
} 

我知道ModifyArray(byte [])應該返回值,但它實際上是一個Socket接收方法。 我也看:

public async Task<byte[]> GetData() 
{ 
    return Task.Run(() => 
    { 
     var _buffer = new byte[1024]; 
     try { ModifyArray(_buffer); } 
     catch { return null;} 

     return _buffer.ToArray(); 
    }); 
} 

,或者我應該移動的ToArray()向外界這樣

public async Task<byte[]> GetData() 
{ 
    return (Task.Run(() => {...});).ToArray(); 
} 

任何有識之士將不勝感激。

+4

線程不安全代碼的標記是一個變量,它由一個線程讀取並由另一個線程寫入。在發佈的代碼片段中沒有明顯的跡象,_buffer是一個局部變量,每個線程都有自己的局部變量。我們看不到什麼是ModifyArray(),它可能是線程不安全的。可能是因爲它使用了一個完全未初始化的數組。但是,張貼沒有明顯的麻煩來源。 –

+0

@HansPassant ModifyArray()實際上是Socket類中的Receive()。我以爲任何線程都可以讀取一個變量,但只有一個可以改變它?我寫的第二個和第三個代碼塊有區別嗎? –

+0

線程安全*針對哪種失敗模式*?你試圖避免的問題是什麼?我的經驗是,沒有兩個人對「線程安全」有相同的定義,所以如果你想得到一個堅實的答案,更具體一些。 –

回答

2

如果要返回數組的快照,但不希望調用者修改內部狀態,則需要創建數組副本。

但這不是你的情況。你在每次調用你的方法時創建一個新的數組,並且你不關心調用者是否修改它(假設ModifyArray()不存儲數組)。

這意味着下面的代碼應該沒問題:

public async Task<byte[]> GetData() 
{ 
    var _buffer = new byte[1024]; 
    await Task.Run(() => ModifyArray(_buffer)); 
    return _buffer; 
} 

另一種選擇是使用最接近的.Net具有「只讀陣列」(在.NET 4.5新)IReadOnlyList<T>

public async Task<IReadOnlyList<byte>> GetData() 
{ 
    var _buffer = new byte[1024]; 
    await Task.Run(() => ModifyArray(_buffer)); 
    return _buffer; 
} 

此外,使用await Task.Run()這樣的是often not a good idea。如果您想最大限度地使用異步,請使用真正的異步方法。如果您想從UI線程中卸載一些計算,請在UI代碼中執行此操作,而不是在您的庫中。