Here is what i want to do. Lets say I have a form with label and 2 listboxes. I want to run
setTime(){
while(true){ label.text = datetime.now.tostring();}
}
setBox1(){
while(true){
items = getitems();
listbox1.items.clear();
for(int i=0;i
}
setBox2(items2){
while(true){
items = getitems2();
listbox2.items.clear();
for(int i=0;i
}
I want to run these constantly without the rest of the program waiting, so i can always display relevant information to my user.
I saw the post http://www.c-sharpcorner.com/uploadfile/835123/cross-thread-operations-in-C-Sharp/ that allows me to update a control using a new thread, but it still makes the program wait for the thread to complete. Why is that? Can't i constantly update a control without interrupting the rest of the program?
I tried background worker a few different ways, but always got either the error that it was busy, or it else it would say i could not access the listbox from a thread other than the one it was created on. There has to be a way to do this, right?
I thought maybe it had something to do with invoke and delegates, but i dont really understand what delegates are or how to use them properly. I have only coded in a single threaded environment and ive hit a wall with it.
Sam HobbsPosted Feb 4, 2012, 12:53 AM
I assume you are using SQL Server. The best solution is to get SQL Server to notify you of changes; that there are changes. I do not know how to do that. Perhaps you can use a trigger, but that is about all I know.
I don't understand how it could work; the code you posted appears to me to not be something that would work. Since it works perhaps you should keep it the way it is.
An alternative is to do away with the background worker. Add a timer to the form and set it to execute every second or whatever. Do the update in the timer tick event. You do not need to be concerned about delegates or cross-thread problems or much of anything. As long as the update can complete fast enough to keep the users happy then that will work. It is not the best but it is the best balance of simplicity and performance.
An alternative would be a combination of the above. You could use a timer and in the timer tick event, use a background worker to get the current data. Then after you have all the updated data, refresh the listbox. I am not sure of the details of how to reuse a background worker but it can be done. This general alternative is possible one way or another.
patrickPosted Feb 3, 2012, 8:50 PM
The idea is to get a list of orders that have not been paid for through getTodaysOrders(), which is a function that runs a mysql command and returns a list of order numbers.
Then I sort through the orders and get the customers associated for them so I can display [order numer]-[customer last name] in a list box.
The database is updated by other systems, so I want to always display a fresh set of orders to the user, while keeping the ui responsive.
Since I last posted, I added a Thread.Sleep(1000) to the beginning of the dowork command.
This seems to work, but I dont think it was the proper way to do it.
Oh the line that read
unPaidCarryoutsStrings.Add(i.ToString() + "-" + CustomerDataHandler.GetCustomerByID(OrdersDataHandler.GetCustomerIDOfOrder(i)).lName);
should have read
OrderCustomerStrings.Add(i.ToString() + "-" + CustomerDataHandler.GetCustomerByID(OrdersDataHandler.GetCustomerIDOfOrder(i)).lName);
where ordercustomerstrings is a variable accessible from both threads, so it gets updated by the dowork, then updates the ui in the workcomplete
Sam HobbsPosted Feb 3, 2012, 8:36 PM
As I understand your code, your DoWork calls fillOrders, which calls getTodaysOrders and then adds the results to unPaidCarryoutsStrings but I do not know what unPaidCarryoutsStrings is.
I see that your bwShowOrders_RunWorkerCompleted event calls bwShowOrders.RunWorkerAsync. That won't work. The bwShowOrders.RunWorkerAsync will cause bwShowOrders_DoWork to execute and then after bwShowOrders_DoWork finishes, the bwShowOrders_RunWorkerCompleted event will called.
Are you doing this because OrdersDataHandler.getTodaysOrders takes a long time? If so, then as best as I understand things, you cannot show any data until OrdersDataHandler.getTodaysOrders finishes. You should use a background worker for a long-running process so that the UI remains responsive but perhaps for your application it is not possible to show any data until all of it has been obtained.
Do I misunderstand where the data is coming from? Is it coming from someplace where there is a delay in getting pieces of it and is the delay caused by something other than the local processor needing time to process the data? If so, then your DoWork would need to do something to wait and I do not see that happening.
I can understand that all of this is confusing. I wish I could make it less confusing. I am confused about what your requirements are.
patrickPosted Feb 2, 2012, 6:42 PM
private void fillOrders()
{
OrderCustomerStrings.Clear(); // this is an object of list
List
foreach(int i in OrderNumbers)
{
unPaidCarryoutsStrings.Add(i.ToString() + "-" + CustomerDataHandler.GetCustomerByID(OrdersDataHandler.GetCustomerIDOfOrder(i)).lName);
}
}
private void bwShowOrders_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
fillOrders();
}
private void bwShowOrders_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
pendingOrdersListBox.DataSource = OrderCustomerStrings;
bwShowOrders.RunWorkerAsync();
}
the idea was that the background worker will constantly update the List
The problem i ran into with this is it runs the cpu at 100% usage, all the time. i dont understand why.
Sam HobbsPosted Feb 2, 2012, 6:31 PM
patrickPosted Feb 2, 2012, 2:32 PM
patrickPosted Feb 2, 2012, 2:31 PM
Sam HobbsPosted Jan 30, 2012, 11:19 PM
I said in your other thread "you can use the ProgressChanged event to update the ListBox" and you are not doing that.