Control.Invoke ...很多控件,需要帮助才能开始...... [英] Control.Invoke...Lots of controls and need help starting...

查看:49
本文介绍了Control.Invoke ...很多控件,需要帮助才能开始......的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,

我开始我的线程工作:


线程t =新线程(新

ThreadStart(invoicePrintingLongRunningCodeThread) );

t.IsBackground = true;

t.Start();


有很多控件调用和许多事件发生在函数调用

来自invoicePrintingLongRunningCodeThread。我只需要一个例子在

开始使用我的线程作业进行调用,这样就可以运行并且不会因为不正确而失败。

这是线程工作(它不是那么长):


private void invoicePrintingLongRunningCodeThread()

{

隐藏();


//listBox1.Items.Add("Network:" + SystemInformation.Network);


if(button7.Text =="& Start Printing Invoices)

{

//临时名称测试

button7.Text = &&;&发票正在处理中;

///在单独的线程中运行


// ThreadStart myThreadDelegate = new

ThreadStart(ThreadFunction1.getOneAtATime);

//线程thr1 =新线程(myThreadDelegate);

// thr1.Start();

bool couNTer1 = false;

do

{

// Form1 findThread = new Form1();

label15.Text = (QUOT; 0" +发票留待打印);

loadInvoiceContainer();

label15.Text =(Convert.ToString(Class1.cI)+"发票留待

打印");

button7.Text ="&观看新发票" ;;

if(Class1.cI> 0)

{

gotoForeach();

}

} while(couNTer1 == false);

}

else

{

// button7.Text ="& Start Printing Invoices";

PrinterBreaks =" BreaksOn";

//线程tid1 =新线程(新

ThreadStart(findThread.getOneAtATime));

// tid1.Abort();

}

}


感谢任何帮助。

谢谢,

Trint

解决方案

当你在非UI线程上运行时,你必须将任何UI请求返回

到主UI线程。 Control上的InvokeRequired属性指定

是否需要调用。这实际上取决于控件的基本

实现是否必须调用它但是一般

安全。规则是你必须只在主UI上与控件交互

线程。一些控件可能会自动处理这种情况,在这种情况下你的代码

就可以了。对于其他人,以下骨架实现是你想要的:

委托void StringDelegate(控制目标,字符串parm);

void SetText(控制目标,字符串文本)

{

if(target.InvokeRequired)

target.Invoke(new StringDelegate(SetText), new object [] {target,text

});

else

target.Text = text;

} $ / $

代码基本上确定它是否在UI线程上运行。如果它没有
那么在UI线程(Control.Invoke)上调用相同的方法。如果

它在UI线程上,那么它只是设置属性。通过更改

委托,调用参数和else块,您可以使用任何属性或方法修改此工作

。请注意,这是一个阻止调用。使用

BeginInvoke / EndInvoke使其异步。


由于性能原因,大多数控件都不会自动实现,但

如果他们不以那种方式迁移,我不会感到惊讶。对于您编写的库代码

来封装这些东西你应该自动为你的来电者做这个

。例如,您不应在主窗体的状态栏上显示进度

栏,而应从主窗体中公开一个方法

以与进度条进行交互。在这种情况下,逻辑上面的

应该封装在你编写的方法中。


另外我还建议你尽量减少你的跨线程调用

和UI互动。我建议构建一个包含

所需UI更改的对象,然后调用一个方法,在线程完成时用对象

内容更新UI(除非这是进度信息)。这个

尤其适用于列表样式的控件,如ListBox和ListView。它b / b
取决于你希望UI如何做出反应。


希望这会有所帮助,

迈克尔泰勒 - 9月16日/ 05


" trint"写道:

好的,
我开始我的线程工作:

线程t =新线程(新的
ThreadStart(invoicePrintingLongRunningCodeThread)) ;
t.IsBackground = true;
t.Start();

有许多控件调用,很多都发生在来自invoicePrintingLongRunningCodeThread的函数调用中。我只需要一个例子来开始使用我的线程作业调用,这样就可以始终运行而不会因为做得不好而失败。
这是线程工作(它'不会那么久):

private void invoicePrintingLongRunningCodeThread()
{
隐藏();

// listBox1.Items.Add(" ;网络:+ SystemInformation.Network;

if(button7.Text =="& Start Printing Invoices)
{
//临时名称测试
button7.Text ="& Invoices正在处理中;
///在单独的线程中运行

// ThreadStart myThreadDelegate = new
ThreadStart(ThreadFunction1。 getOneAtATime);
//线程thr1 =新线程(myThreadDelegate);
// thr1.Start();
bool couNTer1 = false;

{
// Form1 findThread = new Form1();
label15.Text =(" 0" +" Invoices Left to Print&q uot;);
loadInvoiceContainer();
label15.Text =(Convert.ToString(Class1.cI)+"发票留待
打印);
button7.Text ="& Watching for New Inices" ;;
if(Class1.cI> 0)
{
gotoForeach();
}
} while(couNTer1 == false);
}

{
// button7.Text =" &开始打印发票" ;;
PrinterBreaks =" BreaksOn";
//主题tid1 =新主题(新的
ThreadStart(findThread.getOneAtATime));
// tid1 .Abort();
}

任何帮助表示赞赏。
谢谢,
Trint


>有许多控件调用,很多都发生在来自invoicePrintingLongRunningCodeThread的函数调用

中。我只需要一个例子来开始使用我的线程作业调用,这样就可以始终运行而不会因为做得不好而失败。
这是线程工作(它'不会那么久):




再次,我建议查看之前链接的示例代码:
http://www.pobox.com/~skeet/csharp/t ... winforms.shtml


这给出了一个更新两个标签的例子,这是一种

的东西你是

在这里做。基本上,查看您的代码并确定所有内容



更新UI - 并确保按照线程安全的方式运行

文章。


Jon


Michael,

当它到达gotoForeach ();,从那里一个状态栏不断更新,因此有几个标签控件。我将不得不以某种方式

在整个代码中正确地调用控件。

从我给出的剪辑中,它没有显示更新调用的调用



状态栏或文本标签。这是另一个例子,我需要帮助来保护这段代码:

public void PrinterStatusNPI7FC6D2()

{


string trayvalue = string.Empty;

///托盘3

RFC1157.Mgmt mib = new RFC1157.Mgmt();

Snmp.ManagerSession sess = new

Snmp.ManagerSession(Class1.selectLJPrinter," public");

Snmp.ManagerItem mi = new

Snmp.ManagerItem(sess,mib.OID(" 1.3.6.1.2.1.25.3.5.1.1.1"));

// listBox1.Items.Add (" Tray 3" .ToString());

// listBox1.Items.Add(mi.Value.ToString());

trayvalue = Convert.ToString (mi.Value);

label7.Text = string.Format(" Printer Status:{0}",trayvalue);

if(trayvalue ==" ; 0")

{

PrinterBreaks =" BreaksOn";

Tray3 frmText3 = new Tray3();

frmText3.ShowDialog();

}


}


又一个:


statusBarPanel2.Reset();

statusBarPanel2.Step();

statusBarPanel2.ProgressPosition =((long)(Class1 .toNerlOng));


真的很感谢你的帮助。

谢谢,

Trint


Ok,
I start my thread job:

Thread t = new Thread(new
ThreadStart(invoicePrintingLongRunningCodeThread)) ;
t.IsBackground = true;
t.Start();

There are lots of calls to controls and many happen in function calls
from invoicePrintingLongRunningCodeThread. I need just an example in
getting started with my thread job with Invoking so that this will
always run and not fizzle out by not doing it right.
Here is the thread job (it''s not that long):

private void invoicePrintingLongRunningCodeThread ()
{
Hide();

//listBox1.Items.Add("Network : " + SystemInformation.Network );

if (button7.Text == "&Start Printing Invoices")
{
//temp name test
button7.Text = "&Invoices Are Being Processed";
///Run in separate thread

// ThreadStart myThreadDelegate = new
ThreadStart(ThreadFunction1.getOneAtATime);
// Thread thr1 = new Thread(myThreadDelegate);
// thr1.Start();
bool couNTer1 = false;
do
{
// Form1 findThread = new Form1();
label15.Text = ("0" + " Invoices Left to Print");
loadInvoiceContainer();
label15.Text = (Convert.ToString(Class1.cI) + " Invoices Left to
Print");
button7.Text = "&Watching for New Invoices";
if(Class1.cI > 0)
{
gotoForeach();
}
} while (couNTer1 == false);
}
else
{
// button7.Text = "&Start Printing Invoices";
PrinterBreaks = "BreaksOn";
// Thread tid1 = new Thread(new
ThreadStart(findThread.getOneAtATime ) );
// tid1.Abort();
}
}

Any help is appreciated.
Thanks,
Trint

解决方案

As you are running on a non-UI thread you have to push any UI requests back
to the main UI thread. The InvokeRequired property on a Control specifies
whether an invoke is required or not. It really depends on the underlying
implementation of a Control whether or not it must be invoked but the general
"safe" rule is that you must interact with a control only on the main UI
thread. Some controls may handle this automatically in which case your code
would work just fine. For others the following skeleton implementation is
what you want:

delegate void StringDelegate ( Control target, string parm );
void SetText ( Control target, string text )
{
if (target.InvokeRequired)
target.Invoke(new StringDelegate(SetText), new object[] { target, text
});
else
target.Text = text;
}

The code basically determines if it is running on the UI thread. If it
isn''t then in invokes the same method on the UI thread (Control.Invoke). If
it is on the UI thread then it simply sets the property. By changing the
delegate, Invoke arguments and the else-block you can modify this to work
with any property or method. Note that this is a blocking call. Use
BeginInvoke/EndInvoke to make it async.

Most controls don''t implement this automatically for performance reasons but
I wouldn''t be surprised if they don''t migrate that way. For library code
that you write to encapsulate this stuff you should probably do this
automatically for your callers. For example instead of exposing a progress
bar on the status bar of your main form you should instead expose a method
from your main form to interact with the progress bar. In this case the
above logic should be encapsulated in the method you write.

As an aside I would also recommend that you minimize your cross-thread calls
and UI interaction. I''d recommend building an object that contains the
required UI changes and then invoke a method to update the UI with the object
contents when the thread is done (unless this is progress information). This
is especially true of list-style controls like ListBox and ListView. It
depends on how you want your UI to react though.

Hope this helps,
Michael Taylor - 9/16/05

"trint" wrote:

Ok,
I start my thread job:

Thread t = new Thread(new
ThreadStart(invoicePrintingLongRunningCodeThread)) ;
t.IsBackground = true;
t.Start();

There are lots of calls to controls and many happen in function calls
from invoicePrintingLongRunningCodeThread. I need just an example in
getting started with my thread job with Invoking so that this will
always run and not fizzle out by not doing it right.
Here is the thread job (it''s not that long):

private void invoicePrintingLongRunningCodeThread ()
{
Hide();

//listBox1.Items.Add("Network : " + SystemInformation.Network );

if (button7.Text == "&Start Printing Invoices")
{
//temp name test
button7.Text = "&Invoices Are Being Processed";
///Run in separate thread

// ThreadStart myThreadDelegate = new
ThreadStart(ThreadFunction1.getOneAtATime);
// Thread thr1 = new Thread(myThreadDelegate);
// thr1.Start();
bool couNTer1 = false;
do
{
// Form1 findThread = new Form1();
label15.Text = ("0" + " Invoices Left to Print");
loadInvoiceContainer();
label15.Text = (Convert.ToString(Class1.cI) + " Invoices Left to
Print");
button7.Text = "&Watching for New Invoices";
if(Class1.cI > 0)
{
gotoForeach();
}
} while (couNTer1 == false);
}
else
{
// button7.Text = "&Start Printing Invoices";
PrinterBreaks = "BreaksOn";
// Thread tid1 = new Thread(new
ThreadStart(findThread.getOneAtATime ) );
// tid1.Abort();
}
}

Any help is appreciated.
Thanks,
Trint



> There are lots of calls to controls and many happen in function calls

from invoicePrintingLongRunningCodeThread. I need just an example in
getting started with my thread job with Invoking so that this will
always run and not fizzle out by not doing it right.
Here is the thread job (it''s not that long):



Again, I''d suggest looking at the sample code I linked to before:
http://www.pobox.com/~skeet/csharp/t...winforms.shtml

That gives an example of updating two labels, which is the kind of
thing you''re
doing here. Basically, look through your code and identify everything
which
updates the UI - and make sure that runs in a thread-safe manner as per
the article.

Jon


Michael,
When it reaches gotoForeach();, from there a statusbar is constantly
updated and so are several label controls. I will have to somehow
address each call to a control correctly throughout the code.

From the snipit I have given, it doesn''t show the calls to update the


status bar or the text labels. Here is an another example of where I
need help in protecting this code:
public void PrinterStatusNPI7FC6D2()
{

string trayvalue = string.Empty;
///Tray 3
RFC1157.Mgmt mib = new RFC1157.Mgmt();
Snmp.ManagerSession sess=new
Snmp.ManagerSession(Class1.selectLJPrinter,"public ");
Snmp.ManagerItem mi=new
Snmp.ManagerItem(sess,mib.OID("1.3.6.1.2.1.25.3.5. 1.1.1"));
// listBox1.Items.Add("Tray 3".ToString());
// listBox1.Items.Add(mi.Value.ToString());
trayvalue = Convert.ToString(mi.Value);
label7.Text = string.Format("Printer Status: {0}",trayvalue);
if (trayvalue == "0")
{
PrinterBreaks = "BreaksOn";
Tray3 frmText3 = new Tray3();
frmText3.ShowDialog();
}

}

one more:

statusBarPanel2.Reset();
statusBarPanel2.Step();
statusBarPanel2.ProgressPosition = ((long)(Class1.toNerlOng));

Really would appreciate your help.
Thanks,
Trint


这篇关于Control.Invoke ...很多控件,需要帮助才能开始......的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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