gpt4 book ai didi

c# - 在不同线程上初始化表单的实例吗?

转载 作者:行者123 更新时间:2023-12-03 13:22:32 26 4
gpt4 key购买 nike

担心

在WinForms中的主线程以外的其他线程上创建控件/窗体是不好的做法吗?我以为规则只是一个线程不能更改在另一个线程上创建的控件上的某些内容?

场景

我有一个带有一些工作线程的应用程序。这些工作线程可以各自在表单中显示自己的实例。该表单发生的所有事情都保留在该线程内,没有其他线程会尝试对该表单实例做任何事情。该表单具有一些Telerik控件,并且由于将它们升级到了新版本,因此我得到了此处描述的错误类型:

System.Reflection.TargetInvocationException was unhandled
Message="Exception has been thrown by the target of an invocation."
Source="mscorlib"
StackTrace:
at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Delegate.DynamicInvokeImpl(Object[] args)
at System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme)
at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
at System.Threading.ExecutionContext.runTryCode(Object userData)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)
at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at TelerikControlsTest.Program.Main() in C:\Data Files\Projects\Test Projects\TelerikControlsTest\TelerikControlsTest\Program.cs:line 18
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException: System.InvalidOperationException
Message="Object is currently in use elsewhere."
Source="System.Drawing"
StackTrace:
at System.Drawing.Image.get_FrameDimensionsList()
at System.Drawing.ImageAnimator.CanAnimate(Image image)
at Telerik.WinControls.Primitives.ImagePrimitive.get_Image()
at Telerik.WinControls.Primitives.ImagePrimitive.GetImage()
at Telerik.WinControls.Primitives.ImagePrimitive.get_PreferredImageSize()
at Telerik.WinControls.Primitives.ImagePrimitive.MeasureOverride(SizeF availableSize)
at Telerik.WinControls.RadElement.MeasureCore(SizeF availableSize)
at Telerik.WinControls.RadElement.Measure(SizeF availableSize)
at Telerik.WinControls.Layouts.ContextLayoutManager.UpdateLayout()
InnerException:

问题

是否可以在除主应用程序线程之外的其他线程上创建表单实例,还是必须将所有
调用编码回该线程?在我升级Telerik控件之前,这种方法一直有效,因此,要么它们现在有一个新的错误,要么我一直做错了。

请帮忙!

最佳答案

从堆栈跟踪来看,Telerik控件似乎正在共享单个System.Drawing.Image实例,可能是通过某些全局(静态)变量共享的。因为您实例化了不同线程上的控件,所以最终最终无法同时从多个线程访问图像。对于一些使用全局变量的遗留代码(非GUI),我们也有类似的问题。

要回答您的问题:是的,您正在做的事情是可以接受的,但是这种用例很少见,以至于3rdparty控件的供应商可能会决定不支持它。对于它们(或您,如果您有源代码),最简单的解决方法是找到全局变量并使它们成为线程局部的,如下所示:

[ThreadStatic]
static int foo;

这将确保每个线程都有自己的“全局”变量,将它们彼此隔离。

关于c# - 在不同线程上初始化表单的实例吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1272183/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com