我有一个.NET远程客户端激活的对象类型客户端 - 服务器应用程序。我正在使用面向.NET Framework 4的Visual Studio 2010.当我在没有调试的情况下运行时,程序运行正常 - 客户端可以连接没有问题。但是当我尝试调试时,在我拥有'new'运算符的客户端代码中,服务器(我认为)会引发异常。
我想要做的是保持对服务器代码中创建的远程对象的引用。所以在我的Remote Object的构造函数中,我有这一行:
Cache.GetInstance().addFireFighter(this);
当我调试时,这段代码运行正常。但当它返回到远程对象的行以调用addFireFighter
方法时,就会崩溃。这是addFireFighter
方法:
public static IServer _server;
public void addFireFighter(FireFighter ff)
{
_server.addFireFighter(ff);
}
_server.addFireFighter
方法:
public void addFireFighter(FireFighterResponder.FireFighter ff)
{
_ffList.Add(ff); // -> works fine :S
Console.WriteLine("FireFighterResponder addFireFighter added");
lstBox.Items.Add(ff); //-> CRASH!!
}
观察:当我在没有调试的情况下运行服务器但在调试模式下运行客户端时,它仍然可以正常工作。
这是一个学校项目,我是C#.NET远程处理的新手。我在Java中实现了相同的功能,没有任何问题。如果有人想看一下,我可以给我整个项目。也许我有一个设计缺陷。
这是堆栈跟踪:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: Cross-thread operation not valid: Control 'lstBox' accessed from a thread other than the thread it was created on. at System.Windows.Forms.Control.get_Handle() at System.Windows.Forms.ListBox.NativeAdd(Object item) at System.Windows.Forms.ListBox.ObjectCollection.AddInternal(Object item) at System.Windows.Forms.ListBox.ObjectCollection.Add(Object item) at FirefighterMonitorSystem.BaseStation.addFireFighter(FireFighter ff) in C:\Users\Dula\Documents\My Dropbox\Firefighter\453\FirefighterMonitorSystem\FirefighterMonitorSystem\BaseStation.cs:line 35 at FireFighterResponder.Cache.addFireFighter(FireFighter ff) in C:\Users\Dula\Documents\My Dropbox\Firefighter\453\FirefighterMonitorSystem\FireFighterResponder\Cache.cs:line 33 at FireFighterResponder.FireFighter..ctor() in C:\Users\Dula\Documents\My Dropbox\Firefighter\453\FirefighterMonitorSystem\FireFighterResponder\FireFighter.cs:line 20 --- End of inner exception stack trace ---
lstBox
是我的服务器代码中的.NET ListBox
,我在其中添加了每个Remote对象。但是仍然让我感到困惑的是为什么它不在调试模式下工作。
答案 0 :(得分:1)
你必须查看异常的InnerException属性才能知道出了什么问题。
您正在从主线程(也称为UI线程)的线程其他访问控件。这是非法的,Windows不是线程安全的。您必须使用Control.Begin / Invoke()。没有调试器就不会出现异常,因为只有在连接调试器时才会默认启用此线程检查。这并不意味着没有调试器运行代码是安全的,它会随机导致绘制问题或死锁,尽管你可能需要等待一天或一周才能实现。
答案 1 :(得分:0)
抛出的异常是“托管调试助手”
只有在连接调试器时才会发生这种情况,并且正在尝试警告您正在做错事,这些事情大部分时间都会起作用。
在这种情况下,你做错了是从一个创建它的线程以外的线程访问控件lstBox。 (Windows窗体不是线程安全的)
我无法很好地关注您的问题,但我认为您在服务器端对象中有一个方法,它在客户端上调用一个对象。这意味着客户端上运行的代码正在为远程处理基础结构而不是应用程序的主线程服务的线程池线程上运行,因此出现错误。
关于这个错误的问题和Invoke方法(你将用它来修复它)之前已被问过很多次了,这里有一个Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on来看看,我不想做你所有的功课为了你。 :)
一个警告。如果您的应用程序线程仍在等待服务器响应,并且您尝试使用Invoke,那么您的应用程序可能会挂起。例如,你不能这样做 Client Application调用服务器方法foo 服务器方法foo调用客户端方法栏 客户端方法栏使用Invoke来调用客户端方法挂起
对Invoke的调用正在等待主线程,它等待调用Foo完成,等待调用bar完成,等待Invoke完成等待主线程是免费的,这意味着等待Foo的电话完成等等......