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
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
Again, I'd suggest looking at the sample code I linked to before:
http://www.pobox.com/~skeet/csharp/threads/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
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
I am working with your example at this very moment.
How would I be able to use Control.Invoke with updating the status bar
here:
statusBarPanel2.Reset();
statusBarPanel2.Step();
statusBarPanel2.ProgressPosition = ((long)(Class1.toNerlOng));
Thanks,
Trint
Jon
struct UpdateData
{
public UpdateData ( string status, long progress, params string[] items )
{
Status = status;
Progress = progress;
Items = items;
}
public string Status;
public string[] Items;
public long Progress;
}
class MyForm : Form
{
delegate void UpdateStatusDelegate ( UpdateData data );
void UpdateStatus ( UpdateData data )
{
if (InvokeRequired)
Invoke(new UpdateStatusDelegate(UpdateStatus), new object[] { data
});
else
{
foreach(string item in data.Items)
listbox1.Items.Add(item);
label7.Text = data.Status;
statusBarPanel2.Reset();
statusBarPanel2.Step();
statusBarPanel2.ProgressPosition = data.Progress;
};
}
}
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"));
UpdateData data = new UpdateData();
string trayvalue = mi.Value.ToString();
data.Items = new string[] { "Tray 3", trayvalue };
data.Status = String.Concat("Printer Status: ", trayvalue);
f (trayvalue == "0")
{
//This could be bad
PrinterBreaks = "BreaksOn";
Tray3 frmText3 = new Tray3();
frmText3.ShowDialog();
}
//Maybe this is separate??
data.Progress = (long)Class1.toNerlOng;
//UI update
frmObj.UpdateStatus(data);
}
One thing that I'd be concerned about is that form creation in your
secondary thread. That is generally a bad idea because you are creating a
new form on a background thread. I'd try to do that some other way instead.
Michael Taylor - 9/16/05
Michael Taylor - 9/16/05
while (Needs paper)
{
MessageBox.Show("Add paper.");
}
If you don't want to continually prompt the user and their is an external
way (i.e. another thread) to know that the paper has been added then you
should instead use an event. The thread will call ManualResetEvent.WaitOne()
to block until the event is raised. In the other thread once the condition
has been met then set the event. Your paused thread then releases. Note
that in this case you should periodically wake up your thread to check for
other events (such as termination requests) otherwise your thread will never
release until the condition is added.
Michael Taylor - 9/16/05
Michael Taylor - 9/16/05
while (Needs paper)
{
MessageBox.Show("Add paper.");
}
was an excellent idea because the MessageBox is created by the
longrunning thread and not the UI. Right?
Thanks,
Trint
Michael Taylor - 9/19/05
It provides a simple solution to thread-safe UI programming in C#.
"trint" <trinit...@gmail.com> wrote in message
news:1127130657.3...@o13g2000cwo.googlegroups.com...