如何防止多线程? C# [英] How to prevent multithreading? c#

查看:217
本文介绍了如何防止多线程? C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个主窗体,根据用户的选择,我向用户显示控件以及用户所需的信息.

这样,我得到了大约6个用户控制窗口,应该对它们进行适当的管理.

我想要创建一个称为SelectActiveWindow(string windowname)的函数,我将此函数放入新类中,因为我希望每个类都可以访问它.

我在每个类中都使用了Singleton,因为我不想两次创建控件.

我可以使用此功能来管理控件,但无法正常工作,请参见代码:

I have a main form, and depending on the users choice, I show user controls with the information the user needs.

This way I get about 6 user control windows, which should be managed properly.

What I want is to create a function which is called SelectActiveWindow(string windowname) I put this function in a new class, because I want it to be accessable from each class.

I used Singleton in each class, because I do not want to create the controls twice.

I have this function to manage my controls but it does not work properly, please see the code:

 public void SelectActiveWindow(string windowname)
            {
                // Any active control should be hidden thats what this function does:
                HideCurrentActiveControl();
                // Check whether the window is already created
                if (!WindowExists(windowname))
                {
                    // window is not yet created; see which window should be created.
                    switch (windowname)
                    {     
                        case STP_Data.Data.MenuControl:
                            STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.MenuControl;
                            STP_Design.ProgramParameters.C.MenuControlIsCreated = true;
                            // I am getting compiler errors on the following line: It says:
                            // Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on.
                            STP_Design.MenuControl.MenuControl.Instance.Parent = STP2Main.ActiveForm;
                            STP_Design.MenuControl.MenuControl.Instance.Location = new Point(3, 30);
                            STP_Design.MenuControl.MenuControl.Instance.Show();
                            STP_Design.MenuControl.MenuControl.Instance.BringToFront();
                            break;
// here are some more windows to call but not needed to show here.
                    }
            }
            // if the window already exists show the window: 
            else
            {// here is another switch - case structure to show the  window when it does exist



我希望我清楚我想要什么.可能我的工作方法错误,请告诉我什么会更好.



How I hope it is clear what I want. Probably I have a wrong working method, please tell me what would be better. Is there a better way to do this, or an easy way to work around the error I''m getting?

推荐答案

这个问题根本没有道理.如果您确实想防止多线程",则根本不会使用线程.问题不是避免它,而是正确使用线程.您也可以根据线程的关注程度提出一些问题,但是对您的线程什么也不说,也不显示任何与线程相关的代码,这对您也不是一件好事.

由于这些原因,我只会在可以从您的异常信息中获得的信息所允许的范围内进行回答(甚至那也不是很精确:您需要提供全面的异常信息:类型,消息,参数或内部异常,如果任何,表示抛出异常的代码行,等等).实际上,此类问题相对容易解决,因为具备了UI库(System.Windows.Forms,WPF)可以解决这些问题.

您无法从非UI线程调用与UI相关的任何操作.相反,您需要使用System.Windows.Threading.DispatcherInvokeBeginInvoke方法(对于Forms或WPF)或System.Windows.Forms.Control(仅对于Forms).

在我过去的答案中,您将找到有关其工作原理的详细说明和代码示例:
Control.Invoke()与Control.BeginInvoke() [ ^ ],
Treeview扫描仪和MD5的问题 [如何获取keydown事件在vb.net中的不同线程上操作 [启用禁用+多线程后控件事件不会触发 [ ^ ].

我仅假定您的异常是从UI引发的,首先是因为这是最典型的问题,其次是因为您显示了一些UI代码.在更一般的情况下,您需要将一些调用从一个线程委派给另一个线程.特别是,还有许多其他API需要从单个线程进行所有调用,但是应用程序的逻辑通常需要在不同线程中使用此类API.应对此类情况的正确方法是使用单个线程来使用此类API.并且所有其他线程都应将此线程用作服务器来服务那些调用.因此,应该以特殊的方式对此特殊线程进行编程以服务那些请求,并提供一种类似的机制来委派其他线程对其的调用.

要了解如何建立这种机制,请参阅我的文章,并附上源代码和用法示例:
用于线程通信和线程间调用的简单阻塞队列 [ ^ ].

—SA
The question makes no sense at all. If you really wanted to "prevent multithreading", you would not use threads at all. The problem not to avoid it, but to use threads properly. It''s also not very nice for you to ask something based on your threading concern, but to say nothing about your threads, showing no thread-related code.

By these reasons, I''ll answer only to a degree allowed by the information I could get from your exception information (and even that is not precise: you need to provide comprehensive exception information: type, message, parameters or inner exceptions, if any, indicate the line of code where the exception is thrown, etc). Actually, such problems are resolved relatively easily, because the UI libraries (System.Windows.Forms, WPF) are equipped to solve them.

You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].

I only assumed that your exception were thrown from UI, first, because this is the most typical problem, and, second, because you show some UI code. In more general case, you would need to delegate some calls from one thread to another. In particular, there is a number of some other APIs requiring all the call from a single thread, but the logic of your application often requires using such APIs in different threads. The right approach to such situations is to have a single thread to work with such API; and all other threads should use this thread as a server to serve those calls. So, this special thread should be programmed in a special way to serve those requests, and provide a similar mechanism for delegating the calls to it from other threads.

To understand how to make such mechanism, please see my article, complete with source code and usage samples:
Simple Blocking Queue for Thread Communication and Inter-thread Invocation[^].

—SA


这篇关于如何防止多线程? C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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