【问题标题】:Synchronous/Blocking Application.Invoke() for GTK#GTK# 的同步/阻塞 Application.Invoke()
【发布时间】:2010-02-06 13:31:33
【问题描述】:

很遗憾,Application.Invoke() 是异步的:

private string ThreadFunction(int i)
{
    string result = null;

    Gtk.Application.Invoke(delegate
    {
        OutputStringToUserInterface("i = " + i.ToString());
        result = GetStringFromUserInterface();
    });

    return result;
}

这意味着在此示例中,ThreadFunction() 在调用Application.Invoke() 后立即继续,导致result 字符串可能处于未定义状态。 -- 通常ThreadFunction() 会更快并返回旧值(即null)。


这是使用ManualResetEvent 使Application.Invoke() 同步的解决方法:

private string ThreadFunction(int i)
{
    string result = null;

    using (var ev = new ManualResetEvent(false))
    {
        Gtk.Application.Invoke(delegate
        {
            OutputStringToUserInterface("i = " + i.ToString());
            result = GetStringFromUserInterface();

            ev.Set();
        });

        ev.WaitOne();
    }

    return result;
}

这样,ThreadFunction() 会一直等到Application.Invoke() 返回,就像使用WinForms Control.Invoke() 一样。

编辑:更好的示例代码

EDIT2:添加缺少的using


现在我的问题是:有更好的解决方案吗?

【问题讨论】:

    标签: c# .net mono multithreading gtk#


    【解决方案1】:

    嗯,是的,没有理由等待委托执行以获得正确的返回值。修复:

    int result = i + 1;
    

    假设您不经常调用 ThreadFunction() 以至于它会用请求淹没 UI 线程,让 OutputStringToUserInterface() 异步执行是可以的。

    如果您的真实代码实际上依赖于必须在 UI 线程上运行的函数的返回值,那么,不,您不能让它更快。显然,这是你真正想要避免的。

    【讨论】:

    • OK +1。所以你认为没有比上面建议的更好的选择(关于资源消耗)?
    • 资源消耗? ManualResetEvent 非常便宜。
    【解决方案2】:

    您可以将当前代码封装到通用包装器中:

    public static void GuiInvoke(Action action)
    {
        var waitHandle = new ManualResetEventSlim();
        Gtk.Application.Invoke( (s,a) => 
                                {
                                    action();
                                    waitHandle.Set();
                                });
        waitHandle.Wait();
    }
    
    public static void BeginGuiInvoke(Action action)
    {
        Gtk.Application.Invoke( (s,a) => {action();});
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-06
      • 2023-03-14
      • 2013-07-20
      • 2017-08-13
      • 2013-05-07
      • 1970-01-01
      • 2023-03-07
      相关资源
      最近更新 更多