C#线程中的对象初始化 - 无法解释的行为 [英] Object initialization in C# thread - unexplained behaviour

查看:62
本文介绍了C#线程中的对象初始化 - 无法解释的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,


我有一个C#类(在这个例子中,称为A),在它的

构造函数中,启动一个带有a的线程它自己的方法。该线程

将用于持续检查其对象的状态之一和

生成classe'的A事件已连接和断开连接。


它看起来像这样:


"

公共类A

{

私人AnotherObject an_obj;

私人线程thr;

...

公共事件System.EventHandler已连接;

公共事件System.EventHandler已断开连接;


public A()

{

thr = new Thread(new ThreadStart(this.DoThreadWork));

thr.Start();

while(!thr .IsAlive);

thr.IsBackground = true;

}


private void DoThreadWork()

{

an_obj = new AnotherObject();


while(true)

{

if(an_obj.IsPresent())

if(Connected!= null)

Connected(this,EventArgs.Empty);

else

if(Disconnected!= null)

断开连接(this,EventArgs.Empty);

}

}


public void DoSomethingX()

{

an_obj.CallXWork();

}


public int DoSomethingY()

{

返回an_obj.CallYWork();

}

}

"


和使用上一课程的表格:


"

公共类Form1:System.Windows.Forms.Form

{

private A objA;

...


public Form1()

{

objA =新的SmartcardEVController();


objA.Connected + = new EventHandler(objA_Connected);

objA.Disconnected + = new EventHandler(objA_Disconnected);

}


private void objA_Connected(object sender,EventArgs e)

{

objA.DoSomethingX();

}


private void objA_Disconnected(object sender,EventArgs e)

{

int i = objA.DoSomethingY();

MessageBox.Show(" Value:" + i);

}


private void button1_Click(object sender,System.EventArgs e)

{

objA.DoSomethingX();

MessageBox.Show(" Done");

}

}

"

问题在于,虽然每次调用对象objA,但在
内,objA_Connected或objA_Disconnected或捕获的事件工作

完全没问题,当一个方法被调用objA时它在其他任何地方

只会阻止程序执行。在这个例子中,当button1被点击时,指令MessageBox.Show(" Done);"不会被称为

和程序(Form1)将停止响应。


顺便说一下,类AnotherObj是一个C的.NET包装器dll,在
转,是一个Java类的JNI包装器。所有Java方法都是

synchronized。


我认为这可能是Java对象的一个​​问题,但实际上是

是当在objA_Connected内部调用

时,线程内的循环继续执行。或objA_Disconnected或并且那些电话

执行成功,无论拨打多少电话

" objA"。

发生的一件奇怪的事情是单击事件中的调用objA.DoSomethingX();"
使相应的Java方法启动执行(使用Java中的日志实用程序,我可以检查)方法

开始执行但后来没有明显原因停止了。


我现在唯一能想到的是产生的线程< A类中的
有一些自己的内存空间,即在线程内初始化

的对象(an_obj)不能安全使用
。作为生成事件的线程

已连接和断开连接,可以解释在objA_Connected内部调用

object" objA"和objA_Disconnected,

执行得很好。但这只是一个时髦的想法。


p.s。:我也试过初始化对象an_obj。在线程之外,在

classe'的一个构造函数中,但那样的调用an_obj.IsPresent())

也会在C dll中阻塞(这称为JNI代码)没有明显的原因。

如果有人能给我解释为什么会发生这种情况和

我可以做些什么来避免它,我将不胜感激,因为我无法想象它只需要我自己。


谢谢非常,

Ricardo Pereira

解决方案

里卡多,


给我,似乎问题是由于你的

事件是在一个单独的线程中进入,然后它试图访问窗口

元素以外的线程它们是在创建的。当你在MessageBox类上调用

静态Show方法时,它不在主UI线程上。

为了编组调用它正确的线程,你需要调用

调用m在UI线程上创建的控件上的方法(您的表单将是/ b $ b很好)。然后你传递一个委托,指向要在UI线程上调用的方法,以及所需的任何参数。


希望这会有所帮助。< br $> b $ b -

- Nicholas Paldino [.NET / C#MVP]

- mv*@spam.guard.caspershouse.com


" Ricardo Pereira" < PE ********* @ mail.telepac.pt>在消息中写道

news:f1 ************************* @ posting.google.co m ... < Helloquote class =post_quotes> Hello all,

我有一个C#类(在这个例子中,称为A),在它的
构造函数中,用自己的方法启动一个线程。该线程
将用于持续检查其对象的状态之一,并生成classe的A事件已连接状态。和断开连接。

它看起来像这样:

"
公共类A
私人AnotherObject an_obj;
私人线程;


公共事件System.EventHandler已连接;
公共事件System.EventHandler已断开连接;

公开A()
{
thr =新线程(新的ThreadStart(this.DoThreadWork));
thr.Start();
while(!thr.IsAlive);
thr.IsBackground = true;
}
私有空DoThreadWork()
{
an_obj = new AnotherObject();

while(true)
{
if(an_obj.IsPresent())
if(Connected!= null)
Connected(this,EventArgs.Empty);
else
if(Disconnected!= null)
Disconnected(this,EventArgs.Empty);
}
}
公共无效DoSomethingX()
{
an_obj.CallXWork();
}
公共int DoSomethingY()
{
返回an_obj.CallYWork();
} <使用上一课的表单:

"
公共类Form1:System.Windows.Forms .Form
{
私人A objA;
...

公共Form1()
{
objA = new SmartcardEVController();

objA.Connected + = new EventHandler(objA_Connected);
objA.Disconnected + = new EventHandler(objA_Disconnected);
}
私有空objA_Connected (对象发送者,EventArgs e)
{
objA.DoSomethingX();
}
私有空objA_Disconnected(对象发送者,EventArgs e)
{
int i = objA.DoSomethingY();
MessageBox.Show(" Value:" + i);
}
私有的void button1_Click(对象发送者,System.EventArgs e)
{objA.DoSomethingX();
MessageBox。显示(完成);
}
}
 

问题是虽然每次调用对象objA,但内部
并且程序(Form1)将停止响应。

顺便说一下,类AnotherObj是一个C dll的.NET包装器,在
中turn,是Java类的JNI包装器。所有的Java方法都是同步的。

我认为这可能是Java对象的一个​​问题,但事实是,线程内的循环继续执行在objA_Connected内部进行呼叫时或objA_Disconnected或并且这些调用成功执行,无论调用多少次调用对象
objA。
发生的奇怪事情是调用objA.DoSomethingX(); ;在click事件中使得相应的Java方法开始执行(使用Java中的日志实用程序,我可以检查方法
是否开始执行但后来没有明显原因停止)。 />
我现在唯一可以想到的是,A类中产生的线程有一些自己的内存空间,即
在线程内初始化的对象(在线程之外不能安全地使用an_obj。作为生成事件的线程
已连接和断开连接,可以解释对对象对象objA的调用,在objA_Connected内部。和objA_Disconnected,
执行得很好。但那只是一个时髦的想法。

p.s。:我也试过初始化对象an_obj。在线程之外,在
classe'的一个构造函数中,但是那样调用an_obj.IsPresent())
也会在C dll(调用JNI代码)中阻塞no显而易见的原因。
如果有人能给我一个解释为什么会这样的事情,以及我能做些什么来避免它,我会感激,因为我可以''我自己想出来了。

非常感谢,
Ricardo Pereira



Ricardo Pereira< pe ********* @ mail.telepac.pt>写道:


< snip>

如果有人能给我解释为什么会发生这种情况和
我能做什么为了避免这种情况,我将不胜感激,因为我无法独自思考它。




你能发短信但完整吗?演示

问题的程序?


http://www.pobox.com/~skeet/csharp/complete.html 了解详情

我的意思是什么。


删除所有Java的东西,然后只给出一些基于.NET的代码

来显示问题。


顺便说一下,这行是


而(!thr.IsAlive);


是一种非常讨厌的方式等待线程开始 - 一个

循环中的Thread.Sleep调用至少会阻止它*相当*

如此紧张的循环。


(我不管怎么说,我不确定你为什么还要等到它开始之前才开始呢

背景线程。)


同样,我希望an_obj.IsPresent()正在等待或睡觉或

类似的东西,否则你有另一个可能紧的循环

那里 - 永远不是一个好主意。


-

Jon Skeet - < sk *** @ pobox.com>
http://www.pobox.com/~skeet

如果回复群组,请不要邮寄我也是


嗨Ricardo:


A类构造函数中的以下代码行正在放置

调用线程进入无限循环:


while(!thr.IsAlive);


因为你正在创建的线程(thr)也是无限的

而(true)循环。


调用A上的构造函数的线程是用户界面线程,

你不会看到表单刷新或对事件做出反应,直到线程为

免费处理这些事件。


轮询外部对象生成连接和断开

事件将以这种方式非常昂贵。您可以订阅的AnotherObject对象上是否有任何

事件?很难

告诉你需要完成什么,但不知怎的,我想调用

无限的CallXWork不是你想做的。

-

Scott
http:// www.OdeToCode.com

2004年5月31日11:13:08 -0700, pe ********* @ mail.telepac.pt (Ricardo

Pereira)写道:

大家好,

我有一个C#类(在本例中称为A),在其构造函数中,使用自己的方法启动一个线程。该线程
将用于持续检查其对象的状态之一,并生成classe的A事件已连接状态。和断开连接。

它看起来像这样:

"
公共类A
私人AnotherObject an_obj;
私人线程;


公共事件System.EventHandler已连接;
公共事件System.EventHandler已断开连接;

公开A()
{
thr =新线程(新的ThreadStart(this.DoThreadWork));
thr.Start();
while(!thr.IsAlive);
thr.IsBackground = true;
}
私有空DoThreadWork()
{
an_obj = new AnotherObject();

while(true)
{
if(an_obj.IsPresent())
if(Connected!= null)
Connected(this,EventArgs.Empty);
else
if(Disconnected!= null)
Disconnected(this,EventArgs.Empty);
}
}
公共无效DoSomethingX()
{
an_obj.CallXWork();
}

public int DoSomethingY()
{
返回an_obj.CallYWork();
}
}
"

以及使用上一课程的表格:

"
公共类Form1:System.Windows.Forms.Form
{
私人A objA;
...

公共Form1()
{
objA =新的SmartcardEVController();

objA。已连接+ =新EventHandler(objA_Connected);
objA.Disconnected + = new EventHandler(objA_Disconnected);
}
私有void objA_Connected(对象发送者,EventArgs e)
{
objA.DoSomethingX();
}
私有空objA_Disconnected(对象发件人,EventArgs e)
{i /> int i = objA.DoSomethingY ();
MessageBox.Show(" Value:" + i);
}
私有的void button1_Click(对象发送者,System.EventArgs e)
{objA.DoSomethingX();
MessageBox。显示(完成);
}
}
 

问题是虽然每次调用对象objA,但内部
并且程序(Form1)将停止响应。

顺便说一下,类AnotherObj是一个C dll的.NET包装器,在
中turn,是Java类的JNI包装器。所有的Java方法都是同步的。

我认为这可能是Java对象的一个​​问题,但事实是,线程内的循环继续执行在objA_Connected内部进行呼叫时或objA_Disconnected或并且这些调用成功执行,无论调用多少次调用对象
objA。
发生的奇怪事情是调用objA.DoSomethingX(); ;在click事件中使得相应的Java方法开始执行(使用Java中的日志实用程序,我可以检查方法
是否开始执行但后来没有明显原因停止)。 />
我现在唯一可以想到的是,A类中产生的线程有一些自己的内存空间,即
在线程内初始化的对象(在线程之外不能安全地使用an_obj。作为生成事件的线程
已连接和断开连接,可以解释对对象对象objA的调用,在objA_Connected内部。和objA_Disconnected,
执行得很好。但那只是一个时髦的想法。

p.s。:我也试过初始化对象an_obj。在线程之外,在
classe'的一个构造函数中,但是那样调用an_obj.IsPresent())
也会在C dll(调用JNI代码)中阻塞no显而易见的原因。
如果有人能给我一个解释为什么会这样的事情,以及我能做些什么来避免它,我会感激,因为我可以''我自己想出来了。

非常感谢,
Ricardo Pereira



Hello all,

I have a C# class (in this example, called A) that, in its
constructor, starts a thread with a method of its own. That thread
will be used to continuously check for one of its object''s state and
generate classe''s A events "Connected" and "Disconnected".

It looks something like this:

"
public class A
{
private AnotherObject an_obj;
private Thread thr;
...

public event System.EventHandler Connected;
public event System.EventHandler Disconnected;

public A()
{
thr = new Thread(new ThreadStart(this.DoThreadWork));
thr.Start();
while (!thr.IsAlive);
thr.IsBackground = true;
}

private void DoThreadWork()
{
an_obj = new AnotherObject();

while(true)
{
if (an_obj.IsPresent())
if (Connected != null)
Connected(this, EventArgs.Empty);
else
if (Disconnected != null)
Disconnected(this, EventArgs.Empty);
}
}

public void DoSomethingX()
{
an_obj.CallXWork();
}

public int DoSomethingY()
{
return an_obj.CallYWork();
}
}
"

and a form that uses the previous class:

"
public class Form1: System.Windows.Forms.Form
{
private A objA;
...

public Form1()
{
objA = new SmartcardEVController();

objA.Connected += new EventHandler(objA_Connected);
objA.Disconnected += new EventHandler(objA_Disconnected);
}

private void objA_Connected(object sender, EventArgs e)
{
objA.DoSomethingX();
}

private void objA_Disconnected(object sender, EventArgs e)
{
int i = objA.DoSomethingY();
MessageBox.Show("Value: " + i);
}

private void button1_Click(object sender, System.EventArgs e)
{
objA.DoSomethingX();
MessageBox.Show("Done");
}
}
"
The problem is that although every call made to object "objA", inside
the "objA_Connected" or "objA_Disconnected" captured event works
perfectly fine, when a method is called on "objA" anywhere else it
just blocks the program execution. In this example, when button1 is
clicked, the instruction "MessageBox.Show("Done");" won''t get called
and the program (Form1) will stop responding.

By the way, class AnotherObj is a .NET wrapper for a C dll that, in
turn, is a JNI wrapper for a Java class. All Java methods are
"synchronized".

I thought that this could be a problem of the Java object but the fact
is that the cycle inside the thread keeps on executing when calls are
made inside "objA_Connected" or "objA_Disconnected" and those calls
execute successfully, no matter how many calls are made to object
"objA".
A strange thing that happens is that the call "objA.DoSomethingX();"
inside the click event makes the corresponding Java method start
executing (using log utilities in Java, I can check that the method
began execution but then stopped for no apparent reason).

The only thing I can now think of is that the thread that is spawned
in the A class has some kind of own memory space that the object that
was initialized inside the thread ("an_obj") can''t be safely used
outside the thread. Being the thread that generates the events
"Connected" and "Disconnected", that could explain that calls to
object "objA", inside "objA_Connected" and "objA_Disconnected",
executed well. But that''s only an hipothetical thought.

p.s.: I also tried initializing object "an_obj" outside the thread, in
classe''s A contructor, but that way the call "an_obj.IsPresent())"
would also block in the C dll (that calls JNI code) for no apparent
reason.

If anyone could give me an explanation of why this is happening and
what I can do to avoid it, I would be grateful, as I can''t figure it
out just by myself.

Thank you very much,
Ricardo Pereira

解决方案

Ricardo,

To me, it seems that the problem is arising from the fact that your
event is coming in on a separate thread, which then tries to access windows
elements outside of the thread that they were created in. When you call the
static Show method on the MessageBox class, it is not on the main UI thread.
In order to marshal the call to the correct thread, you need to call the
Invoke method on a control that is created on the UI thread (your form would
be fine). You then pass a delegate pointing to the method to be called on
the UI thread, along with any parameters that are needed.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Ricardo Pereira" <pe*********@mail.telepac.pt> wrote in message
news:f1*************************@posting.google.co m...

Hello all,

I have a C# class (in this example, called A) that, in its
constructor, starts a thread with a method of its own. That thread
will be used to continuously check for one of its object''s state and
generate classe''s A events "Connected" and "Disconnected".

It looks something like this:

"
public class A
{
private AnotherObject an_obj;
private Thread thr;
...

public event System.EventHandler Connected;
public event System.EventHandler Disconnected;

public A()
{
thr = new Thread(new ThreadStart(this.DoThreadWork));
thr.Start();
while (!thr.IsAlive);
thr.IsBackground = true;
}

private void DoThreadWork()
{
an_obj = new AnotherObject();

while(true)
{
if (an_obj.IsPresent())
if (Connected != null)
Connected(this, EventArgs.Empty);
else
if (Disconnected != null)
Disconnected(this, EventArgs.Empty);
}
}

public void DoSomethingX()
{
an_obj.CallXWork();
}

public int DoSomethingY()
{
return an_obj.CallYWork();
}
}
"

and a form that uses the previous class:

"
public class Form1: System.Windows.Forms.Form
{
private A objA;
...

public Form1()
{
objA = new SmartcardEVController();

objA.Connected += new EventHandler(objA_Connected);
objA.Disconnected += new EventHandler(objA_Disconnected);
}

private void objA_Connected(object sender, EventArgs e)
{
objA.DoSomethingX();
}

private void objA_Disconnected(object sender, EventArgs e)
{
int i = objA.DoSomethingY();
MessageBox.Show("Value: " + i);
}

private void button1_Click(object sender, System.EventArgs e)
{
objA.DoSomethingX();
MessageBox.Show("Done");
}
}
"
The problem is that although every call made to object "objA", inside
the "objA_Connected" or "objA_Disconnected" captured event works
perfectly fine, when a method is called on "objA" anywhere else it
just blocks the program execution. In this example, when button1 is
clicked, the instruction "MessageBox.Show("Done");" won''t get called
and the program (Form1) will stop responding.

By the way, class AnotherObj is a .NET wrapper for a C dll that, in
turn, is a JNI wrapper for a Java class. All Java methods are
"synchronized".

I thought that this could be a problem of the Java object but the fact
is that the cycle inside the thread keeps on executing when calls are
made inside "objA_Connected" or "objA_Disconnected" and those calls
execute successfully, no matter how many calls are made to object
"objA".
A strange thing that happens is that the call "objA.DoSomethingX();"
inside the click event makes the corresponding Java method start
executing (using log utilities in Java, I can check that the method
began execution but then stopped for no apparent reason).

The only thing I can now think of is that the thread that is spawned
in the A class has some kind of own memory space that the object that
was initialized inside the thread ("an_obj") can''t be safely used
outside the thread. Being the thread that generates the events
"Connected" and "Disconnected", that could explain that calls to
object "objA", inside "objA_Connected" and "objA_Disconnected",
executed well. But that''s only an hipothetical thought.

p.s.: I also tried initializing object "an_obj" outside the thread, in
classe''s A contructor, but that way the call "an_obj.IsPresent())"
would also block in the C dll (that calls JNI code) for no apparent
reason.

If anyone could give me an explanation of why this is happening and
what I can do to avoid it, I would be grateful, as I can''t figure it
out just by myself.

Thank you very much,
Ricardo Pereira



Ricardo Pereira <pe*********@mail.telepac.pt> wrote:

<snip>

If anyone could give me an explanation of why this is happening and
what I can do to avoid it, I would be grateful, as I can''t figure it
out just by myself.



Could you post a short but complete program which demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.

Cut out all the Java stuff and just give some bare-bones .NET-only code
which shows the problem.

By the way, the line

while (!thr.IsAlive) ;

is a pretty nasty way of waiting for the thread to start - a
Thread.Sleep call in the loop would at least stop it from being *quite*
such a tight loop.

(I''m not sure why you''re waiting for it to start before making it a
background thread anyway, to be honest.)

Similarly, I hope an_obj.IsPresent() is waiting or sleeping or
something similar, otherwise you''ve got another potentially tight loop
there - never a good idea.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too


Hi Ricardo:

The following line of code in class A''s constructor is putting the
calling thread into an infinite loop:

while (!thr.IsAlive);

Because the thread you are creating (thr) is also in an infinite
while(true) loop.

The thread calling the constructor on A is the user interface thread,
you won''t see the form refresh or react to events until the thread is
free to process those events.

Polling the outside object to generate the connect and disconnect
events will in this fashion will be very expensive. Are there any
events on the AnotherObject object you can subscribe to? It''s hard to
tell what you need to accomplish but somehow I think invoking
CallXWork infinitely is not what you want to do.

--
Scott
http://www.OdeToCode.com
On 31 May 2004 11:13:08 -0700, pe*********@mail.telepac.pt (Ricardo
Pereira) wrote:

Hello all,

I have a C# class (in this example, called A) that, in its
constructor, starts a thread with a method of its own. That thread
will be used to continuously check for one of its object''s state and
generate classe''s A events "Connected" and "Disconnected".

It looks something like this:

"
public class A
{
private AnotherObject an_obj;
private Thread thr;
...

public event System.EventHandler Connected;
public event System.EventHandler Disconnected;

public A()
{
thr = new Thread(new ThreadStart(this.DoThreadWork));
thr.Start();
while (!thr.IsAlive);
thr.IsBackground = true;
}

private void DoThreadWork()
{
an_obj = new AnotherObject();

while(true)
{
if (an_obj.IsPresent())
if (Connected != null)
Connected(this, EventArgs.Empty);
else
if (Disconnected != null)
Disconnected(this, EventArgs.Empty);
}
}

public void DoSomethingX()
{
an_obj.CallXWork();
}

public int DoSomethingY()
{
return an_obj.CallYWork();
}
}
"

and a form that uses the previous class:

"
public class Form1: System.Windows.Forms.Form
{
private A objA;
...

public Form1()
{
objA = new SmartcardEVController();

objA.Connected += new EventHandler(objA_Connected);
objA.Disconnected += new EventHandler(objA_Disconnected);
}

private void objA_Connected(object sender, EventArgs e)
{
objA.DoSomethingX();
}

private void objA_Disconnected(object sender, EventArgs e)
{
int i = objA.DoSomethingY();
MessageBox.Show("Value: " + i);
}

private void button1_Click(object sender, System.EventArgs e)
{
objA.DoSomethingX();
MessageBox.Show("Done");
}
}
"
The problem is that although every call made to object "objA", inside
the "objA_Connected" or "objA_Disconnected" captured event works
perfectly fine, when a method is called on "objA" anywhere else it
just blocks the program execution. In this example, when button1 is
clicked, the instruction "MessageBox.Show("Done");" won''t get called
and the program (Form1) will stop responding.

By the way, class AnotherObj is a .NET wrapper for a C dll that, in
turn, is a JNI wrapper for a Java class. All Java methods are
"synchronized".

I thought that this could be a problem of the Java object but the fact
is that the cycle inside the thread keeps on executing when calls are
made inside "objA_Connected" or "objA_Disconnected" and those calls
execute successfully, no matter how many calls are made to object
"objA".
A strange thing that happens is that the call "objA.DoSomethingX();"
inside the click event makes the corresponding Java method start
executing (using log utilities in Java, I can check that the method
began execution but then stopped for no apparent reason).

The only thing I can now think of is that the thread that is spawned
in the A class has some kind of own memory space that the object that
was initialized inside the thread ("an_obj") can''t be safely used
outside the thread. Being the thread that generates the events
"Connected" and "Disconnected", that could explain that calls to
object "objA", inside "objA_Connected" and "objA_Disconnected",
executed well. But that''s only an hipothetical thought.

p.s.: I also tried initializing object "an_obj" outside the thread, in
classe''s A contructor, but that way the call "an_obj.IsPresent())"
would also block in the C dll (that calls JNI code) for no apparent
reason.

If anyone could give me an explanation of why this is happening and
what I can do to avoid it, I would be grateful, as I can''t figure it
out just by myself.

Thank you very much,
Ricardo Pereira




这篇关于C#线程中的对象初始化 - 无法解释的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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