方法是由多个线程在C#中使用访问进度 [英] Method accessed by more than one thread in C# Using Progressbar

查看:577
本文介绍了方法是由多个线程在C#中使用访问进度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有多个线程访问的方法。

I have multiple threads accessing a method.

这方法将更新为线程执行表单上的进度条。

That method updates the progress bar on the form as the threads execute.

这方法更新进度条在我的窗口形式显示已处理的文件作为线程进程正在完成他们。

That method updates the progress bar on my windows form showing the progress of the processed files as the threads are completing them.

你怎么会去有关管理方法,以避免死锁。有林烦锁了,不知道如果即时通讯做是错误的,或者我应该锁定在这种情况下。

How would you go about managing that method to avoid deadlocks. Im having trouble locking it, dont know if im doing it wrong, or if i should lock it in this case.

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呼吁,并进一步要求都是非法的。

What happens is, that at the last line, it breaks telling me that "This operation has already had OperationCompleted called on it and further calls are illegal."

我认为,即时通讯打开一个已经布置在第一的东西螺纹或类似的东西。

I take it that im opening something that has already been disposed by the first thread or something like that.

这是一个很好的方式去使用多线程的进度条(我是否有正确的理念或原则),还是有只是在我的代码,一个小错误?

Is this a good way to go about using the progress bar with multiple threads (do i have the right idea or principle), or is there just a small error in my code?

我多么想使这个问题其他人可贵的是,这个问题怎么全局变量,这是一个方法内访问回答由多个线程被访问。
,因为我把它这就是这个问题的的发展方向。

How I want to make this question valuable for other people is to answer with this question how global variables can be accessed inside a method that's being accessed by multiple threads. since i take it thats the direction this question is going in.

推荐答案

看起来你正在使用的BackgroundWorker的类,我不熟悉。

It looks like you're using the BackgroundWorker class, which I'm not familiar with.

但你也要求使用多个线程和进度通用的设计。这个例子是我从多个线程更新进度的方式。

But you're also asking for a "generic" design for using multiple threads and ProgressBar. This example would be my way for updating a ProgressBar from a number of threads.

首先,你需要一个公共委托(可能在一些辅助类)

First, you need a public delegate (probably in some helper-class)

//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;
    }
}

在每个工人类,你必须注册代理

In each worker class you must register the delegate

// 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问题)的线程中执行。

In the UI class which holds the ProgressBar you need a method for updating the progress. But every call to that method is executed in the thread of the caller (which can be problematic with the not-threadsafe UI).

要避免这种情况,你可以调用调度,使每个引发的事件会在你的UI线程来处理,而不是工作线程。

To avoid this, you can call the dispatcher, so that every raised event will be handled in your UI thread and not the worker thread.

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;
    }
}

这方法,你可以传递给工人的代表

This method you can pass to the worker as delegate

worker.RegisterEventHandler(StatusUpdate);



最后,你可以从每个线程

Finally you can call the delegate via an event from every thread

public void DoVeryHardWork()
{
    // do stuff
    ProgressChanged(this, new ProgressEventArgs(progress, "some message"));
}

这篇关于方法是由多个线程在C#中使用访问进度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆