简体   繁体   English

C#中的线程安全

[英]Thread-safety in C#

I have currently been assigned a project that was implemented couple of years ago in C#. 我目前已经分配了一个项目,该项目是几年前在C#中实现的。 It consists of frames and some excel-files extraction, but the problem is that this project is extremly broken/outdated and I have to change some functionalities and add some new feature. 它由框架和一些excel文件提取组成,但问题是这个项目极度破坏/过时,我必须改变一些功能并添加一些新功能。

There are some libraries that are supported only after .NET framework 3.0 that I need to use in the new features,and the framework that the current project was built on is 2.0 or less,so changing the framework raised some thread safety problems. 有一些库只在我需要在新功能中使用的.NET Framework 3.0之后才受支持,并且构建当前项目的框架是2.0或更少,因此更改框架会引发一些线程安全问题。

Between two partial classes for example which are the design file code and the backend code trying to change one label's value raises an error saying that I can not edit something that is being used at the moment... I used delegates for one of the labels, and it worked fine..then the other textbox raised another error.. So is there an option to encapsulate the whole thing and apply thread safety to the whole code without having to follow each line where the error happens? 在两个部分类之间,例如设计文件代码和尝试更改一个标签值的后端代码引发错误,表示我无法编辑当前正在使用的内容...我使用委托作为其中一个标签,它工作得很好..然后另一个文本框引发了另一个错误..那么是否有一个选项来封装整个事情并将线程安全应用于整个代码而不必遵循错误发生的每一行?


Edit from comments 从评论中编辑

Exception : 例外

Exception while Saving Links. Exception: System.InvalidOperationException: Cross-thread operation not valid: Control 'picLinkUBKCross' accessed from a thread other than the thread it was created on.

Code who seams to fail 接近失败的代码

this.picLinkUBKCross.Image = ((System.Drawing.Image) resources.GetObject("picLinkUBKCross.Image"))); 
this.picLinkUBKCross.Location = new System.Drawing.Point(367, 57);
this.picLinkUBKCross.Name = "picLinkUBKCross"; 
this.picLinkUBKCross.Size = new System.Drawing.Size(56, 35); 
this.picLinkUBKCross.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.picLinkUBKCross.TabIndex = 14;
this.picLinkUBKCross.TabStop = false; 

If your project contains errors in it's multi-thrading code that with the new Framework and Thread-handling advance from weird glitches to actual exceptions (which is a good thing) there is nothing you can do but tackle these errors one after another. 如果你的项目包含错误的多重代码,新的框架和线程处理从奇怪的故障发展到实际的异常(这是一件好事),除了一个接一个地处理这些错误之外你无能为力。 There is no magic to fix all buggy code with one silver bullet. 用一颗银弹来修复所有有缺陷的代码是没有魔力的。

So if you have switched the framework i think you also switched your Visual Studio version? 所以,如果你已经切换框架,我认为你也改变了你的Visual Studio版本?

Within VS you can configure if you like to see the Cross-Thread exception and i think in your old version this hint was simply switched off. 在VS中,您可以配置是否要查看Cross-Thread exception ,我认为在旧版本中,这个提示只是被关闭了。 So all your problems already exists in your old code but now you see it again. 因此,您的旧代码中已存在所有问题,但现在您再次看到它。

If you try to set (and sometimes even get) some information from a gui control you must ensure that you do this within the gui thread and not from any other. 如果你试图设置(有时甚至得到)来自gui控件的一些信息,你必须确保你在gui线程内而不是从任何其他线程中执行此操作。 The problem is that it could work, but that can't be ensured (and maybe only crashs on the customer machine). 问题是它可以工作,但无法确保(并且可能只在客户机器上崩溃)。

So please consider these exception as a real problem within your tool that must be fixed as soon as possible. 因此,请将这些异常视为工具中的一个真正问题,必须尽快修复。

Either you go within your gui thread and call WindowsFormsSynchronizationContext.Current; 要么进入你的gui线程并调用WindowsFormsSynchronizationContext.Current; and pass the received object to your other threads so that they can call Post() or Send() on them or if you have direct access to a control you simply call control.Invoke() or control.BeginInvoke() on it. 并将接收到的对象传递给其他线程,以便它们可以调用它们上的Post()Send() ,或者如果您可以直接访问控件,则只需在其上调用control.Invoke()control.BeginInvoke()

Maybe you should also take a look at this SO question . 也许你也应该看看这个问题

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

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