繁体   English   中英

C#是action.BeginInvoke(action.EndInvoke,null)一个好主意吗?

[英]C# Is action.BeginInvoke(action.EndInvoke,null) a good idea?

如果我想对某些代码进行“一劳永逸”,但仍希望确保清理我的内存( 为什么异步委托方法需要调用EndInvoke? ),以下是否会实现这一目标?

Action myAction = () => LongRunTime();
myAction.BeginInvoke(myAction.EndInvoke,null);

我环顾四周,但没有看到任何地方使用过的模式。 相反,人们使用annonomoyus方法作为他们的回调(例如结束BeginInvoke的正确方法? )或者他们定义一个实际的回调方法。 由于我没有看到其他人这样做,这让我觉得它要么不起作用,要么是一个坏主意。

谢谢!

使用方法组转换而不是委托很好,仍然会在Action上调用EndInvoke 没有别的事情要做,因为这是一场火灾和忘记的召唤。

不幸的是,直接无可辩驳地证明EndInvoke被调用有点困难,因为Action是一个委托,我们不能只在BCL中的某个类上添加断点。

此代码将(定期)检查BeginInvoke返回的IAsyncResult的某个私有字段,这似乎跟踪是否已调用EndInvoke

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;
            }
        }
    }
}

我使用SOS进行了双重检查,发现没有任何托管内存泄漏。 我也尝试了其他一些证据,但我认为它们比这个证据更具间接性。

我在调查期间发现了一些有趣的内容: myAction.BeginInvoke调用将使用检测显示在探查器上,但myAction.EndInvoke则不会。

现在可以这样做

BeginInvoke((Action)(async () =>
{
    // Show child form
    var f = new MyForm();
    f.ShowDialog();
    // Update parent/current
    await UpdateData();
}));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM