多线程和套接字问题,帮帮我 [英] MultiThread and Socket problem, help me

查看:88
本文介绍了多线程和套接字问题,帮帮我的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

lbTinhTrang.Dispatcher.BeginInvoke ((Action) (() =>; {lbTinhTrang.Content = "str";}), DispatcherPriority.Normal);



使用此代码,当您不更改标签的内容但
时没有错误



with this code no error when you do not change the content for the label but

myGrid.Dispatcher.BeginInvoke ((Action) (() =>; {myGrid.Children.Add (_rec);}), DispatcherPriority.Normal);



然后您会看到此错误

"The calling thread cannot access this object because a different thread owns it."

据我了解,我更改了标签内容,它只是创建标签的一个线程,但是使用myGrid是由于添加了一个新的UI,该UI线程已在套接字中声明,因此它也是myGrid声明添加另一个线程不应该.

我在Google上搜索,但仍然无法解决,请他指导.我做了一个类似错误的小演示

我做了一个有错误的演示类似物
http://www.mediafire.com/?azv7xhp9rv4v3m9 [



Then you see this error

"The calling thread cannot access this object because a different thread owns it."

as I understand it, I change the label content, it is only one thread creating the label, but with myGrid is due to add a new UI that this UI thread is declared in the socket, it is also myGrid declaration to add another thread should not be.

I search on google but still can not fix, expect him to guide me. I made ​​a small demo with similar errors

I make a demo simlar with error
http://www.mediafire.com/?azv7xhp9rv4v3m9[^]

推荐答案

您都做错了.您只需要一个Dispatcher和一个呼叫InvokeBeginInvoke呼叫-在您的情况下,两者都可以工作.

您在代码中所做的事情大为混乱:您为每个小调用创建了一个单独的调用队列项,并将两个线程混合在一起.您使用BeginInvoke异步添加了几个调用.原则上,这是可能的,但是请考虑一下:通过BeginInvoke,您将两个相关的和竞争 UI调用放入了调用队列,而不必等待每个完成!这样,您将依赖于一定的完成顺序,这有潜在的危险!

我对您的代码做了很少的修改.首先,由于不使用窗口实例,因此我从窗口实例的范围中删除了一个线程声明(在这种情况下,可以使用BackgroundWorker,但是我知道代码纯粹是实验性的,因此您可能真正需要该类成员-生活代码);对于此示例,我将其设置为堆栈变量.我还重命名了所有自动生成的对象,以提醒您应遵循(良好的)Microsoft命名约定.我还将"rec_"重命名为"rec",以遵循堆栈变量的命名约定.我从XAML中删除了事件处理程序,以将所有代码放入窗口构造函数中(我还删除了仅使用一次的所有方法,以简化代码并使用匿名方法演示该技术,并使代码更短):

You did it all wrong. You need only one Dispatcher and only one call Invoke or BeginInvoke call — in your case, both will work.

What you have done in your code was a big mess: you created a separate invocation queue item for each small call and mixed the two thread. You added several invocations asynchronously using BeginInvoke. In principle it would be possible, but think about it: by BeginInvoke you put two related and competing UI calls to the invocation queue without waiting for the completion of each! In this way, you rely on certain order of completion, which is potentially dangerous!

I''ve done few modifications of your code. First, I removed a thread declaration form the scope of window instance as you don''t use it (you could use BackgroundWorker for this case, but I understand the code is purely experimental, so you may need this class member in real-life code); for this example, I made it a stack variable. I also renamed all auto-generated objects to remind you that you should follow (good) Microsoft naming conventions; I also renamed "rec_" to "rec", to follow naming conventions for stack variables. I removed event handler from XAML to put all code in the window constructor (I also removed all methods you used only once to simplify code and demonstrate the technique using anonymous methods and make the code shorter):

using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Threading;

//...

public MainWindow() { //window class constructor
   InitializeComponent();
   buttonThread.Click += (sender, eventArgs) => {
       Thread thread = new Thread(() => {
            gridTest.Dispatcher.Invoke(new Action(() => {
                Rectangle rec = new Rectangle();
                rec.Width = gridTest.Width / 2; //changed to show effect
                rec.Height = gridTest.Height;
                rec.Fill = Brushes.Black;
                rec.HorizontalAlignment = HorizontalAlignment.Left;
                rec.VerticalAlignment = VerticalAlignment.Top;
                gridTest.Children.Add(rec);
            })); //thread body
        }); //buttonThread.Click
        //thread.SetApartmentState(ApartmentState.STA); //no need
        thread.Start();
    }; //buttonThread.Click
} //MainWindow



您还应该清理使用情况.使用Visual Studio,您可以方便地使用上下文菜单整理使用情况"-> 删除未使用的用法".

顺便说一句,越来越多的人抱怨您如何呈现代码以供审查:您应该对其进行更多清理:删除未使用的引用,删除未使用的资源"和"Settings.settings",更重要的是,删除所有不在您的文件中的文件.源代码:"*.suo","*.user",.\ obj \ *.*",.\ bin \ *.*".

除此之外,我非常感谢您提出问题报告的方式!每个询问者都应创建一些简单的示例. 您真的帮助我修复了您的代码.

有关invocaion的更多详细信息,请检查我过去的答案:
Control.Invoke()与Control.BeginInvoke() [ ^ ],
Treeview Scanner和MD5的问题 [如何将ref参数传递给线程 [ ^ ].

—SA



You should also clean-up your using. With Visual Studio, you can conveniently use context menu "Organize Usings" -> "Remove Unused Usings".

By the way, more complains on how you present your code for review: You should clean it more: remove unused references, remove unused "Resourses" and "Settings.settings", and, more importantly, remove all files which are not in your source code: "*.suo", "*.user", ".\obj\*.*", ".\bin\*.*".

Other then that, I really appreciate the way you present your issue report! Every Inquirer should create some simple sample. You really helped me to fix your code.

For more detail on invocaion, please check my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

For the thread creation, use this convenient technique of thread wrapper:
How to pass ref parameter to the thread[^].

—SA


这篇关于多线程和套接字问题,帮帮我的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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