我正在開發一個C#UWP 10解決方案,該解決方案使用快速,持續的讀/寫循環與網絡設備進行通信。由API提供的StreamSocket似乎工作得很好,直到我意識到存在內存泄漏:堆中有大約Task<uint32>
的積累,每分鐘數百次。爲什麼在循環中使用StreamSocket會導致內存泄漏?
是否我使用普通老式while (true)
環的async Task
內部,或者使用自發布ActionBlock<T>
與TPL數據流(根據this answer),其結果是一樣的。
我可以,如果我消除從套接字進行讀取來進一步隔離問題並專注於寫作: 無論我用DataWriter.StoreAsync
方法或更直接的StreamSocket.OutputStream.WriteAsync(IBuffer buffer)
,問題依舊。此外,將這些.AsTask()
添加到這些沒有任何區別。
即使垃圾收集器運行,這些Task<uint32>
也不會從堆中移除。所有這些任務都已完成(RanToCompletion
),沒有任何錯誤或任何其他屬性值可能表示「尚未完全準備好回收」。
this page(從託管世界到非託管世界阻止內存釋放的字節數組)似乎暗示了我的問題,但是規定的解決方案看起來很明顯:唯一的解決方法是編寫所有C++/CX中的通信邏輯。我希望這不是真的;當然,其他C#開發人員已經成功實現了無內存泄漏的持續高速網絡通信。而微軟肯定不會沒有內存泄漏在C++/CX
編輯
按照要求,一些示例代碼釋放只能的API。我自己的代碼層數太多,但使用this Microsoft sample可以觀察到更簡單的示例。我做了一個簡單的修改,在循環中發送1000次以突出問題。這是相關代碼:
public sealed partial class Scenario3 : Page
{
// some code omitted
private async void SendHello_Click(object sender, RoutedEventArgs e)
{
// some code omitted
StreamSocket socket = //get global object; socket is already connected
DataWriter writer = new DataWriter(socket.OutputStream);
for (int i = 0; i < 1000; i++)
{
string stringToSend = "Hello";
writer.WriteUInt32(writer.MeasureString(stringToSend));
writer.WriteString(stringToSend);
await writer.StoreAsync();
}
}
}
在啓動應用程序和連接插口,還有的Task<UInt32>
堆上唯一實例。點擊「SendHello」按鈕後,有86個實例。第二次按下後:129個實例。
編輯#2 運行我的應用程序之後(緊循環發送/接收)3小時,我可以看到,有絕對是一個問題:50萬分任務的情況下,它從來沒有得到GC'd,應用的進程內存從最初的46 MB增加到了105 MB。很明顯,這個應用程序不能無限期地運行。 但是 ...這隻適用於運行在調試模式。如果我編譯我的應用程序版本模式,部署它並運行它,沒有內存問題。我可以讓它整夜運行,很明顯內存管理正常。 案件關閉。
發佈代碼展示問題 – alexm
@alexm,請參閱發佈的代碼。 Thx – BCA
@BCA - 當您在事件處理程序中引用全局對象時,它如何能夠收集頁面? –