我坚持上述问题。我有很多解决方案,但没有一个能为我工作。 请在此处找到我的代码
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;
}
当它执行“Invoke(new MyDelegate(ShowProgressBar),(Int32)(currentCount * 100 / totalCount));”时这条线超出了范围。它进入内部,永远不会回来。而且也没有陷入异常。
有人可以帮我解决这个问题吗?
谢谢, 马赫什
答案 0 :(得分:5)
必须从创建它的线程访问控件progressBar
。使用BeginInvoke。
我会替换这一行...
Invoke(new MyDelegate(ShowProgressBar), (Int32)(currentCount * 100 / totalCount));
......这个......
this.progressBar.BeginInvoke(
(MethodInvoker)delegate() {
this.progressBar.Value =
Convert.ToInt32(currentCount * 100 / totalCount); } );
或者你可以替换这些线......
progressBar.Value = percentage;
progressBar.Refresh();
//txtLogDetails.Text = message;
......按这些方式......
this.progressBar.BeginInvoke(
(MethodInvoker)delegate() {
progressBar.Value = percentage;
progressBar.Refresh();
//txtLogDetails.Text = message;
} );
答案 1 :(得分:0)
我认为问题在于您使用Thread.Join来阻止UI线程。
Thread.Join理论上会继续提供UI消息,但实际上它并不总是有效。
请参阅Chris Brumme的博客here。特别
净效果是我们将始终为等待进入您的STA的COM呼叫提供泵送。任何发送到任何窗口的SendMessages都将得到服务。但是大多数PostMessages都会被延迟,直到你完成阻止。
你应该让按钮事件完成并让新线程在完成后回发消息(例如通过使用backgroundworker或其他异步框架)
(你的catch语句无论如何都是无用的,因为它只能捕获线程创建异常。)