Sử dụng chuyển đổi nhóm phương pháp thay vì ủy quyền là tốt, EndInvoke
sẽ vẫn được gọi trong số Action
của bạn. Không có gì khác để được thực hiện, vì đây là một ngọn lửa và quên cuộc gọi. Thật không may, nó hơi khó để chứng minh trực tiếp rằng EndInvoke được gọi, vì Action
là một đại biểu và chúng tôi không thể chỉ thêm một điểm ngắt trên một số lớp trong BCL.
Mã này sẽ (theo định kỳ) kiểm tra một số lĩnh vực riêng của IAsyncResult được trả về bởi BeginInvoke
, mà dường như để theo dõi hay không EndInvoke
đã được gọi nào:
public partial class MainWindow : Window
{
private Timer _timer = new Timer(TimerCallback, null, 100, 100);
private static IAsyncResult _asyncResult;
public MainWindow()
{
InitializeComponent();
}
static void LongRunTime()
{
Thread.Sleep(1000);
}
void Window_Loaded(object sender, RoutedEventArgs args)
{
Action myAction =() => LongRunTime();
_asyncResult = myAction.BeginInvoke(myAction.EndInvoke, null);
}
static void TimerCallback(object obj)
{
if (_asyncResult != null)
{
bool called = ((dynamic)_asyncResult).EndInvokeCalled;
if (called)
{
// Will hit this breakpoint after LongRuntime has completed
Debugger.Break();
_asyncResult = null;
}
}
}
}
Tôi đã hai lần kiểm tra sử dụng SOS rằng không có bất kỳ rò rỉ bộ nhớ được quản lý nào. Tôi cũng đã thử một số bằng chứng khác, nhưng chúng hoàn toàn khác với chứng minh này, tôi nghĩ vậy.
Một số điều thú vị tôi đã khám phá trong quá trình điều tra: cuộc gọi myAction.BeginInvoke
sẽ hiển thị trên các trình sử dụng thiết bị, nhưng myAction.EndInvoke
thì không.
Tôi không thấy bất kỳ sự cố nào khi sử dụng chuyển đổi nhóm phương thức qua biểu thức lambda. – Thorarin
Nếu bạn có thể thêm câu trả lời theo cách này hay cách khác, nếu kỹ thuật này không gây rò rỉ bộ nhớ thì đó sẽ là câu trả lời mà tôi đang tìm kiếm. Cảm ơn! –