避免跨线程操作错误的最简洁正确的方法? [英] Most concise and proper way of avoiding cross thread operation error?

查看:53
本文介绍了避免跨线程操作错误的最简洁正确的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不太擅长代理,也不了解幕后发生的事情.从不同线程访问 UI 项时出现 cross thread operation 错误.

I am not pretty good at delegates and I don't get what's happening under hood. I get the cross thread operation error when accessing UI items from a different thread.

我想要做的是在 Utility 类中编写一个通用函数,以便我可以将任何方法/代码块传递给该函数.我可以通过多种方式做到这一点:

What I want to do is write a generic function in a Utility class so that I pass can any method/code block to the function. I can do it many ways like:

delegate void UpdateGui(Control c, Action action);
public static void Do(Control c, Action action)
{
    try
    {
        if (c.InvokeRequired)
        {
            UpdateGui updaterdelegate = new UpdateGui(Do);
            c.TopLevelControl.Invoke(updaterdelegate, new object[] { c, action });
        }
        else
            action();
    }
    catch (Exception ex)
    {
        //throw ex;
    }
}

  • public static void Do(Control c, Action action)
    {
        try
        {
            if (c.InvokeRequired) 
            {
                c.TopLevelControl.Invoke((Action)delegate { Do(c, action); });
            }
            else
                action();
        }
        catch (Exception ex)
        {
            //throw ex;
        }
    }
    

  • public static void Do(Control c, Action action)
    {
        try
        {
            if (c.InvokeRequired)
            {
                c.TopLevelControl.Invoke(action);
            }
            else
                action();
        }
        catch (Exception ex)
        {
            //throw ex;
        }
    }
    

  • public static void Do(Control c, Action action)
    {
        try
        {
            if (c.InvokeRequired) 
            {
                c.TopLevelControl.Invoke(new MethodInvoker(() => action()));
            }
            else
                action();
        }
        catch (Exception ex)
        {
            //throw ex;
        }
    }
    

  • public static void Do(Control c, Action action)
    {
        try
        {
            if (c.InvokeRequired) 
            {
                c.TopLevelControl.Invoke(new MethodInvoker(delegate { action(); }));
            }
            else
                action();
        }
        catch (Exception ex)
        {
            //throw ex;
        }
    }
    

  • public static void Do(Control c, Action action)
    {
        try
        {
            if (c.InvokeRequired) 
            {
                c.TopLevelControl.Invoke((MethodInvoker)delegate { action(); });
            }
            else
                action();
        }
        catch (Exception ex)
        {
            //throw ex;
        }
    }
    

  • 我相信方法 1 和方法 2 基本相同,方法 4、5 和 6 也是如此.我的问题是:

    I believe approaches 1 and 2 are essentially the same, and 4, 5 and 6 as well. My questions are:

    1. 方法 (1 & 2)、3 和 (4, 5 & 6) 之间有什么区别?我的意思是在哪些情况下一个人处理/照顾另一个人不做?

    1. What's the difference between approaches (1 & 2), 3 and (4, 5 & 6)? I mean what would be the cases where one handles/takes care of which other does not?

    避免跨线程操作错误的正确方法是什么,它处理所有情况,最好是简洁易读?

    What's the proper way of avoiding cross thread operation error, in the sense it handles all the situations, preferably concise and readable?

    推荐答案

    您上面的第三种"方法(仅使用 Action)更简单、更高效.您使用 delegate 的其他方法创建一个单独的方法(通过 delegate 关键字的匿名方法),然后调用您的原始委托(action 参数),这是不必要的.

    Your "third" approach above (just using the Action) is simpler and more efficient. Your other approaches using delegate create a separate method (anonymous method via the delegate keyword) which then calls your original delegate (the action parameter), which is unnecessary.

    第三个选项直接使用传入的Action,比较简单.

    The 3rd option just directly uses the Action passed in, which is simpler.

    第一个选项是类似的,但在这种情况下,您传递的是不必要的值(Control),并且必须定义一个自定义委托(尽管您可以使用 Action 代替).由于未使用控件,因此没有理由增加这种复杂性.

    The first option is similar, though in that case, you're passing in values that aren't necessary (the Control) plus having to define a custom delegate (though you could use Action<Control,Action> instead). As the Control isn't being used, there is no reason to add this complexity.

    附带说明 - 当您在异常处理程序中重新抛出时,最好只使用 throw;(而不是 throw ex;),因为这样将正确保留堆栈跟踪:

    On a side note - when you rethrow within your exception handler, it'd be better to just use throw; (and not throw ex;), as this will preserve the stack trace properly:

    catch (Exception ex)
    {
        // Do whatever, ie: logging
        throw;
    }
    

    如果您不打算登录,而只是打算重新抛出,则可以完全省略 try/catch.

    If you're not going to log, and just plan to rethrow, you can leave out the try/catch entirely.

    这篇关于避免跨线程操作错误的最简洁正确的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆