Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么System.Threading.Timer回调成功更新UI?_C#_Winforms_Multithreading_Thread Safety - Fatal编程技术网

C# 为什么System.Threading.Timer回调成功更新UI?

C# 为什么System.Threading.Timer回调成功更新UI?,c#,winforms,multithreading,thread-safety,C#,Winforms,Multithreading,Thread Safety,我的表单应用程序上有几个System.Threading.Timer,它们带有回调,可以成功地更新UI,也就是说,不会抛出错误 在我知道UI不应该在UI线程之外的任何线程上更新之前,我就已经构建了这些 现在我很困惑,当我在这些单独的threading.timer线程上更新UI时,为什么它不抛出跨线程异常 我将更改这些回调,以便在UI线程上调用UI更新,但我很好奇为什么会这样 编辑:我的应用程序是WinForms应用程序 我将更改这些回调,以便在UI线程上调用UI更新,但我很好奇为什么会这样 如果

我的表单应用程序上有几个System.Threading.Timer,它们带有回调,可以成功地更新UI,也就是说,不会抛出错误

在我知道UI不应该在UI线程之外的任何线程上更新之前,我就已经构建了这些

现在我很困惑,当我在这些单独的threading.timer线程上更新UI时,为什么它不抛出跨线程异常

我将更改这些回调,以便在UI线程上调用UI更新,但我很好奇为什么会这样

编辑:我的应用程序是WinForms应用程序

我将更改这些回调,以便在UI线程上调用UI更新,但我很好奇为什么会这样

如果这是Windows窗体,那么它完全是靠运气工作的。在后台线程上更新UI不会一直有效,但偶尔不会抛出错误。特别是,如果是错误的,它有时会“起作用”,而且永远不会抛出——尽管这种行为通常是错误的。有些控件并不总是检查每个属性,因此有些项“工作”,即使它们并不总是正常工作,因为这通常会引入一些以后很难诊断和纠正的错误

附带说明:如果这是WPF,那么可以在后台线程上更改绑定到UI的项的值,从而有效地更新UI。WPF绑定系统将自动为您将其封送到UI线程。但是,更改集合的一部分不起作用

我将更改这些回调,以便在UI线程上调用UI更新,但我很好奇为什么会这样

如果这是Windows窗体,那么它完全是靠运气工作的。在后台线程上更新UI不会一直有效,但偶尔不会抛出错误。特别是,如果是错误的,它有时会“起作用”,而且永远不会抛出——尽管这种行为通常是错误的。有些控件并不总是检查每个属性,因此有些项“工作”,即使它们并不总是正常工作,因为这通常会引入一些以后很难诊断和纠正的错误


附带说明:如果这是WPF,那么可以在后台线程上更改绑定到UI的项的值,从而有效地更新UI。WPF绑定系统将自动为您将其封送到UI线程。但是,更改集合的一部分不起作用。

我在WinForms中也遇到过这种情况。请看这里:在我看来,它是通过“魔法”(阅读“以随机方式”)起作用的,不应该被视为在实践中邀请这样做。这绝不是更新GUI的线程安全方式。有时程序不会抱怨。

我在WinForms中也遇到过这种情况。请看这里:在我看来,它是通过“魔法”(阅读“以随机方式”)起作用的,不应该被视为在实践中邀请这样做。这绝不是更新GUI的线程安全方式。有时程序不会抱怨。

在.NET 1.0和1.1中,不会执行跨线程检查,因此您永远不会得到
无效操作异常
(尽管MSDN承认执行跨线程更新“通常会导致不可预知的结果”,这可能包括应用程序崩溃)

在.NET 2.0及更高版本中,根据静态属性的值执行交叉线程检查。它的默认值是从static属性初始化的(该属性指示是否将调试器附加到进程),这意味着当应用程序单独运行时(没有连接Visual Studio或任何其他调试器),不会执行跨线程检查


当然,此设置可能会被用户代码(包括引用的库)覆盖。

在.NET 1.0和1.1中,不会执行跨线程检查,因此您永远不会得到
InvalidOperationException
(尽管MSDN承认执行跨线程更新“通常会导致不可预知的结果”),这可能包括应用程序崩溃)

在.NET 2.0及更高版本中,根据静态属性的值执行交叉线程检查。它的默认值是从static属性初始化的(该属性指示是否将调试器附加到进程),这意味着当应用程序单独运行时(没有连接Visual Studio或任何其他调试器),不会执行跨线程检查


当然,此设置可能会被用户代码(包括引用的库)覆盖。

我认为这与您创建的计时器类型有关。有两种类型:

    System.Timers.Timer;
    System.Windows.Forms.Timer 
这两者之间有明显的区别,如果更新UI,System.Timers.Timer将引发异常,System.Windows.Forms.Timer将不会。如果您有一个using语句:“using System.Windows.Forms”并且只是有一个“Timer”,那么这将是Windows.Forms.Timer,它与System.Timers.Timer明显不同


在后台(我相信)System.Windows.Forms.Timer正在捕获WM_Timer消息,因此您正在更新GUI的线程上。

我相信这与您创建的计时器类型有关。有两种类型:

    System.Timers.Timer;
    System.Windows.Forms.Timer 
这两者之间有明显的区别,如果更新UI,System.Timers.Timer将引发异常,System.Windows.Forms.Timer将不会。如果您有一个using语句:“using System.Windows.Forms”并且只是有一个“Timer”,那么这将是Windows.Forms.Timer,它与System.Timers.Timer明显不同


在后台(我相信)System.Windows.Forms.Timer正在捕获WM_Timer消息,因此您正在更新GUI的线程上。

您能给我们看一些代码吗??我认为这项工作不像你的答案那样纯粹是靠运气。。我从来没有见过它不失败就工作。@gbianchi它取决于控件的更新。某些控件在签入时优于其他控件