|
No, you still get the problem, just you don't see it because the thread that fails isn't the main thread.
You can't update UI controls from a non UI thread - you are getting a cross threading exception. Use Invoke to move teh listBox update back onto the UI thread and it should be fine.
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
OriginalGriff wrote: Use Invoke to move teh listBox update back onto the UI thread and it should be fine.
Or it would be fine, if he wasn't blocking the UI thread waiting for the background thread to complete!
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Good point - since the Invoke call waits for the delegate to return a value, you should get a deadlock.
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
Thanks to both of you for your valuable help. Changed it as shown below and got it working without loosing sequence and with corresponding thread id...
private void TaskRunButton_Click(object sender, EventArgs e)
{
listBox.Items.Clear();
Task demoTask = new Task(DemoTask);
demoTask.Start();
}
private void DemoTask()
{
try
{
List<Task> tsk1 = new List<Task>();
List<Task> tsk2 = new List<Task>();
for (int i = 0; i < 10; i++)
{
tsk1.Add(new Task(TaskDemoWait100ms));
tsk2.Add(new Task(TaskDemoWaitWait200ms));
}
for (int i = 0; i < 10; i++)
{
tsk1[i].Start();
tsk2[i].Start();
tsk2[i].Wait();
listBox.BeginInvoke(new separatorDelegate(() =>
{ listBox.Items.Add("------------"); }));
}
}
catch (Exception ex)
{
string msg = ex.Message;
}
}
delegate void taskdelegate(int threadId);
delegate void separatorDelegate();
private void TaskDemoWait100ms()
{
Thread.Sleep(100);
object[] param = new object[1];
param[0] = (object)Thread.CurrentThread.ManagedThreadId;
listBox.BeginInvoke(new taskdelegate((int threadId) =>
{ listBox.Items.Add("Wait 100 ms, Thread Id = " + threadId); }), param);
}
private void TaskDemoWaitWait200ms()
{
Thread.Sleep(200);
object[] param = new object[1];
param[0] = (object)Thread.CurrentThread.ManagedThreadId;
listBox.BeginInvoke(new taskdelegate((int threadId) =>
{ listBox.Items.Add("Wait 200 ms, Thread Id = " + threadId); }), param);
}
|
|
|
|
|
I don't see any failing thread, because I am getting the values in the list box correctly, but as you mentioned, it may fail at any time.
Thanks very much for your valuable inputs. I will work on this and update further...
|
|
|
|
|
Why are you starting a new task and then immediately waiting for it? You're blocking the UI thread waiting for a background thread to complete, so you might as well just do the work on the UI thread.
I suspect the reason you're getting an exception is because you're updating a UI control from a non-UI thread. You will need to use the Invoke method to ensure that the updates only happen on the UI thread.
Unfortunately, since you've chosen to block the UI thread waiting for the background thread to complete, this won't work - the UI thread is blocked waiting for the background thread to complete, and the background thread is blocked waiting for the UI thread to process the Invoke message.
You might be able to work around the problem by using BeginInvoke instead, which won't block the background thread. However, this will change the behaviour of your code, as the list items will not be added in the same sequence.
If you're using .NET 4.5, try using async / await instead:
private async Task SynchronousWait200ms()
{
await Task.Delay(200);
listBox.Items.Add("Wait 200 ms, Thread Id = " + Thread.CurrentThread.ManagedThreadId);
}
private async void TaskRunButton_Click1(object sender, EventArgs e)
{
listBox.Items.Clear();
for (int i = 0; i < 10; i++)
{
await SynchronousWait200ms();
}
listBox.Items.Add("------------");
}
That should work, but you'll get the same thread ID for each item, as the code will be marshalled back to the UI thread.
Perhaps if you explain what you're trying to achieve, we might be able to help.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
modified 19-Jun-14 10:19am.
|
|
|
|
|
Thanks very much for your thoughts.
Yes, Invoke also blocks as you mentioned. BeginInvoke solves the issue, but sequence goes wrong.
Regarding async / await, I am aware of it. In the project from where I took the code and posted here, it has async / await sample also. I am working on a sample for async / await. In that same sample I wanted to add Task.Start() as an example to demonstrate the use of Task.Wait() via another button on the UI. That's the reason I am doing wait immediately after Task.Start()
|
|
|
|
|
Hi masters, sorry for my question title.
Iam confused what the good sentence for this topic.
Example i use SendKeys.Send("^f"); to open "Find and Replace" menu in excel.
I have to open the file before use sendkey method.
Then after all process finished, workbook will appear and followed by the window of "Find and Replace" menu.
Is possible to show the window of "Find and Replace" menu only without workbook appear?
I just want to use excel search system in my program.
Sorry for my bad english, thank you.
|
|
|
|
|
No you can't. The Find and Replace dialog is an integral part of the Excel UI. Plus, what exactly would you be searching if you didn't have the workbook open? How would you know that you had found things for a start?
|
|
|
|
|
Oh. I think to make search system for excel.
If button clicked, the window of "Find and Replace" is appear without workbook, or maybe the workbook is invisible.
If "find" button clicked, then this time the workbook is appear.
Okay thank you
|
|
|
|
|
bonjot wrote: Is possible to show the window of "Find and Replace" menu only without workbook appear?
No. You must have a workbook open, otherwise the Find and Replace dialog doesn't make any sense.
You can try this yourself. Just launch Excel and close the default workbook that opens. Can you use Find and Replace then? Nope.
bonjot wrote: I just want to use excel search system in my program.
Can't be done. Excels Find and Replace will only work with workbooks/worksheets inside Excel.
|
|
|
|
|
Yeah, if i close workbook, find and replace window is closed too
thank you master
|
|
|
|
|
Please Help
I am developing a C# windows form with a Data Grid View with list view
Task:-
Perform faster insert and update from a C# application
I have to inserting huge data (around 100,000 rows or more) from a list view/grid or data table to a SQL Server database.
How to improve the speed of the following loop which takes more then 3Hours and going outbound. Is there any other way
Eg:
Calculate button click event -> calculation part -> fill list view
total_emp = 100,000;
lvloanDetails.Items.Clear();
for (int i = 0; i < total_emp; i++)
{
ListViewItem lvi = new ListViewItem(emp_id.ToString("D2"));
loan_balance get from =(formula/additions/diductions/calculations)
lvi.SubItems.Add(loan_balance.ToString("#,0.00"));
lvLoanDetails.Items.Add(lvi);
i++;
}
Process button click event -> list view’s data insert in to sql database table
for (int i = 0; i < lvLoanDetails.Item.Count; i++)
{
insert -> list view to sql
i++;
}
|
|
|
|
|
I'm sorry, but your code really confuses me. Why are you doing i++ in the body of your for loops? Which part do you think is really causing the issue because the way you are creating your listview here is going to be really slow.
|
|
|
|
|
Why the heck are you putting 100,000 items into a list view?
Do you hate your users?
Or did you not think "What would this be like to use?" as well as "why is this slow?"
Don't. No user on this planet is going to sit there and look through 100,000 rows of information - they need it abstracted, sorted, searchable, filterable, just to bring the volume down to a meaningful level.
Use a List or a DataTable, and do a bulk insert into SQL, or do each row as you create it (though that is slower) - but don't try to put it into anything like a display control!
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
Thanks a lot for your suggestion,
But there are some calculations to be done. is it a good idea and best way to use the same in Database - Store procedure?
And also, 100,000 rows will not be in UI, rather will do some calculation to get the summery to update on the database.
|
|
|
|
|
If they aren't in the UI, then why would you waste time and resources putting them into a UI control, which has to do a fair amount of processing every time you add an element?
Let's go back a stage: you have 100,000 items of information. Where do they come from? What are you doing with them? How many results do you get from these items? How much of this are you inserting into the DB?
Because it may be that you are going completely the wrong way!
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
Wrong tool for the job (as OG said) and probably the wrong place as well. If you MUST do this in the client app (winforms) then use a collection or datatable (if you are inserting 100k records then use bulk insert from a datatable) to hold the data not a UI control.
If you are looking up the loan details from the database then consider inserting the emp details without the loan info and do an update in the database, this will take advantage of the grunt a database brings to processing volume records.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Thanks
What about Store Procedure to achieve this process?
|
|
|
|
|
I would put all the data into a datatable via your loop, insert that into a staging table using bulkcopy. Then craft a stored proc that implements the loan function on each record as it is inserted into your final destination table either as a single record or a set depending on your function.
You still have not mentioned the database you are using.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
The database is MS SQL (2008)
|
|
|
|
|
That's just details of implementation.
You'll never get very far if all you do is follow instructions.
|
|
|
|
|
A stored procedure is a bit moot, your primary issue is the number of database calls that you're making. Drop it to one call and you should see a dramatic increase in performance.
Some of the more reasonable solutions I've seen revolve around using SqlBulkCopy[^]
|
|
|
|
|
Either you bulk load or you make sure to not recreate the connection each time in the loop.
I often user StringBuilder concatenation and send 1000 insert queries in one go...
so you would have something like:
StringBuilder builder = new StringBuilder("");
for(int i = 0; i < someLength;i++){
builder.append(the insert query + ";");
if(i%1000 == 0){
ExecuteQuery(builder.ToString());
builder = new StringBuilder("");
}
}
Hope this gives you an idea.
|
|
|
|
|
I am using the following code
Uri collectionUri = new Uri(@"http://XXX.XXX.XXX.XXX:8080/tfs/projectcollection");
TfsTeamProjectCollection teamProjectCollection =
new TfsTeamProjectCollection(collectionUri, new NetworkCredential(@"user","userpassword"));
teamProjectCollection.EnsureAuthenticated();
WorkItemStore workItemStore = teamProjectCollection.GetService<WorkItemStore>();
string wiql = "SELECT [System.Id], [System.WorkItemType], [System.Title], [System.AssignedTo], [System.State] FROM WorkItems " +
"WHERE [System.TeamProject] = 'Pathway' " + "AND [System.State] = 'System Test Complete' " +
"AND [Sagitec.Common.TestPhase] = '4.B – System Testing' ORDER BY [System.Id]";
WorkItemCollection workItemCollection = workItemStore.Query( wiql);
foreach (WorkItem wi in workItemCollection)
{
wi.Fields["Assigned To"].Value = "Srikanth";
wi.Fields["State"].Value = "Ready for Client Review";
wi.Fields["Reason"].Value = "Ready for Client Review";
MessageBox.Show(wi.Fields["Assigned To"].Value + " + " + wi.Fields["State"].Value + " + " + wi.Fields["Reason"].Value);
}
Now, when i see the values of respective Fields in workitem object, they are not holding the values that I have set. Instead they have value which is already there in the workitem. I checked about ByPassRules. But I dont see the enum WorkItemStoreFlags in my namespace. Can you please help me in setting the values for fields values in my workitem?
|
|
|
|