我有多个线程访问的方法。
该方法更新进度条的形式为线程执行。
该方法将更新我的windows窗体上的进度条显示为线程完成他们处理文件的进度。
你会如何去有关管理方法,以避免死锁。 林有麻烦锁定它,不知道是否即时通讯做是错误的,或者我应该锁定在这种情况下。
public void myWorkerClass()
{
int amountToScan = 4;
lblcount.BeginInvoke(
((Action)(() => lblcount.Text = "Files Checked " + atPDFNumber.ToString() + " of " + amountToScan.ToString())));
decimal percentageComplete = ((decimal)atPDFNumber / (decimal)amountToScan) * 100;
backgroundWorker1.ReportProgress((int)percentageComplete);
}
什么情况是,在最后一行,它打破告诉我,“这次行动已经有OperationCompleted呼吁,并进一步要求是非法的。”
我认为,即时通讯开放的东西,已经被布置在第一线或类似的东西。
这是去使用多线程(我是否有正确的理念或原则)的进度条的好办法,或者是有只是一个小错误在我的代码?
我要如何让其他人这个问题,可贵的是,这个问题怎么全局变量多数民众赞成由多个线程访问的方法内访问回答。 因为我把它那这个问题中去的方向。
它看起来像你使用BackgroundWorker类,我不熟悉。
但你也要求使用多线程和进度“通用”的设计。 这个例子是我从多个线程更新进度条的方式。
首先,你需要一个公共委托(可能是在一些辅助类)
//is called when the worker-progress is changed
public delegate void ProgressChangedHandler(object sender, ProgressEventArgs e);
// some own EventArgs
public class ProgressEventArgs : EventArgs
{
public int Percentage { get; private set; }
public string Message { get; private set; }
public ProgressEventArgs(int percentage, string message)
{
Percentage = percentage;
Message = message;
}
}
在每个工人类,你必须注册代理
// event for reporting progress
private event ProgressChangedHandler ProgressChanged;
// register Eventhandler via dependency injection or own method
public void RegisterDelegate(ProgressChangedHandler progressChangedHandler)
{
ProgressChanged += progressChangedHandler;
}
在其持有进度的UI类,你需要更新进度的方法。 但该方法每次调用在调用者(可以是与不是线程安全UI问题)的线程中执行。
为了避免这种情况,你可以调用调度,使每个引发的事件会在你的UI线程来处理,而不是工作线程。
private void StatusUpdate(object sender, ProgressEventArgs args)
{
if (Dispatcher.Thread.ManagedThreadId != Thread.CurrentThread.ManagedThreadId)
{
// call from a worker thread
var statusUpdateDelegate = new ProgressChangedHandler(this.StatusUpdate);
Dispatcher.Invoke(statusUpdateDelegate, DispatcherPriority.Normal, sender, args);
}
else
{
// direct call from the UI thread
lblProgress.Content = args.Message;
pbProgress.Value = args.Percentage;
}
}
这种方法可以传递给工人的代表
worker.RegisterEventHandler(StatusUpdate);
最后,您可以通过从每个线程的事件调用该委托
public void DoVeryHardWork()
{
// do stuff
ProgressChanged(this, new ProgressEventArgs(progress, "some message"));
}