c# - Progress Bar [Threading] Cross-thread operation not valid: Control 'progressBar' accessed from a thread other than the thread it was created on
I am stuck with the above issue. I got lot of solutions but none of them working for me. Please find herewith my code
private void btnRunQuery_Click(object sender, EventArgs e)
{
try
{
Thread ProcessThread = new Thread(Process);
ProcessThread.Start();
Thread.CurrentThread.Join();
}
catch
{
Debug.WriteLine("Error in model creation");
Console.WriteLine("Error in model creation");
}
finally
{
//dsModel = null;
}
}
private void Process()
{
using (var dataContext = new IControlerDataContext())
{
dataContext.EnlistTransaction();
IItemPropertyRepository itemPropertyRepository = ObjectContainer.Resolve<IItemPropertyRepository>();
IList<ItemProperty> itemPropertyCollection = itemPropertyRepository.LoadAll();
totalCount = itemPropertyCollection.Count;
currentCount = 0;
foreach (var itemProperty in itemPropertyCollection)
{
try
{
message = string.Empty;
currentCount++;
if (itemProperty.DeletedDate == null && (itemProperty.MetaItemProperty.ValueType == MetaItemPropertyValueType.MetaItemTableProperty || itemProperty.MetaItemProperty.ValueType == MetaItemPropertyValueType.MetaItemTableMultiSelectProperty))
{
//Property refresh issue in only applicable for table and multitable property.
//Need to filter the itemproperty for Table and multitable select property.
message = ProcessItemProperty(itemProperty);
//txtLogDetails.Text += message + Environment.NewLine;
//txtLogDetails.Refresh();
//txtLogDetails.ScrollToCaret();
}
开发者_如何学运维 //Log(message);
//progressBar.Value = (Int32)(currentCount * 100 / totalCount);
//progressBar.Refresh();
Invoke(new MyDelegate(ShowProgressBar), (Int32)(currentCount * 100 / totalCount));
}
catch (Exception ex)
{
txtLogDetails.Text += "EXCEPTION ERROR : " + itemProperty.Id.ToString();
dataContext.RollBackTransaction();
}
}
dataContext.CompleteTransaction();
}
}
delegate void MyDelegate(int percentage);
private void ShowProgressBar(int percentage)
{
progressBar.Value = percentage;
progressBar.Refresh();
//txtLogDetails.Text = message;
}
When it is executing " Invoke(new MyDelegate(ShowProgressBar), (Int32)(currentCount * 100 / totalCount));" this line it goes out of scope. It goes inside and never came back. and also havn't caught in exception.
Can anyone please help me out from this?
Thanks, Mahesh
The control progressBar
must be accessed from the thread that it was created on. Use BeginInvoke.
I would replace this line ...
Invoke(new MyDelegate(ShowProgressBar), (Int32)(currentCount * 100 / totalCount));
... by this one ...
this.progressBar.BeginInvoke(
(MethodInvoker)delegate() {
this.progressBar.Value =
Convert.ToInt32(currentCount * 100 / totalCount); } );
Or you can replace those lines ...
progressBar.Value = percentage;
progressBar.Refresh();
//txtLogDetails.Text = message;
... by those lines...
this.progressBar.BeginInvoke(
(MethodInvoker)delegate() {
progressBar.Value = percentage;
progressBar.Refresh();
//txtLogDetails.Text = message;
} );
I think the problem is that you block the UI thread with Thread.Join.
Thread.Join will in theory continue to pump UI messages but in reality it doesn't always work.
see Chris Brumme's blog here. Specially
The net effect is that we will always pump COM calls waiting to get into your STA. And any SendMessages to any windows will be serviced. But most PostMessages will be delayed until you have finished blocking.
You should let the button event finish and have the new thread post back a message when it is done (e.g. by using backgroundworker or some other async framework)
(Your catch statement is useless anyway since it will only catch thread creations exceptions.)
精彩评论