时间:2019-03-17 标签:c#ProgressBarproblem

发布于 2024-08-15 16:00:56 字数 3159 浏览 3 评论 0原文

我一直在寻找一种方法来创建一个漂亮的进度条。 我找到了一些我使用的代码,如果我使用循环,它会很好地工作。但现在我想在一个真正像样的应用程序中使用它,这给我带来了很多麻烦。我有一个在 IMDB 上查找数据的应用程序,因此我连接到 IMDB,例如 500 个电影标题,所以这需要一段时间。因此,我想显示一个进度条,进度条会随着查找的每部电影而增长,并提供有关电影标题的一些额外信息。

我使用以下类:

public partial class ProgressDialog : Window, IProgressContext
{
    public ProgressDialog()
    {
        InitializeComponent();
        IconBitmapDecoder ibd = new IconBitmapDecoder(
        new Uri("IMDB.ML.ico", UriKind.RelativeOrAbsolute),
        BitmapCreateOptions.None, BitmapCacheOption.Default);
        this.Icon = ibd.Frames[0];
    }
    public void UpdateProgress(double progress)
    {
        Dispatcher.BeginInvoke(DispatcherPriority.Background,
            (SendOrPostCallback)delegate { Progress.SetValue(ProgressBar.ValueProperty, progress); }, null);
    }

    public void UpdateStatus(string status)
    {
        Dispatcher.BeginInvoke(DispatcherPriority.Background,
            (SendOrPostCallback)delegate { StatusText.SetValue(TextBlock.TextProperty, status); }, null);
    }

    public void Finish()
    {
        Dispatcher.BeginInvoke(DispatcherPriority.Background,
            (SendOrPostCallback)delegate { Close(); }, null);
    }
}

public interface IProgressContext
{
    void UpdateProgress(double progress);
    void UpdateStatus(string status);
    void Finish();
}

这是使用进度条的 imdb 查找方法,此方法使用现有的 xml 列表,因此它仅用于更新数据,而不是添加新电影:

public static void updateIMDBinfo()
    {

        //initialize progressbar
        ProgressDialog myProgressContext = new ProgressDialog();
        myProgressContext.Show();            

        //load old list
        List<Movie> movieList = XML.getMovieList();

        //create new updated list
        List<Movie> newMovieList = new List<Movie>();
        int count = 1;
        foreach (Movie movie in movieList)
        {
            //update progressbar
            myProgressContext.UpdateProgress((double)count / (double)movieList.Count);
            myProgressContext.UpdateStatus(String.Format("Updating movie: '{0}' ({1}/{2})", movie.Title, count, movieList.Count));

            movie.Link = movie.Link.Substring(movie.Link.IndexOf("http://www.imdb.com/title/") + 26, 9);

            //this creates a new movie where it looks up the data from imdb
            newMovieList.Add(new Movie(movie.Title, movie.Link, movie.Path));

            count++;
        }

        //sort the list
        newMovieList.Sort((Movie m1, Movie m2) => m1.Title.CompareTo(m2.Title));

        //save as xml
        XML.updateMovieList(newMovieList);

        //finish progressbar
        myProgressContext.Finish();
    }

所以现在当我使用该方法时,它会打开进度条,但是该栏永远不会填满,它只是不断将电影添加到列表中并查找更新的信息,而不填满该栏。我认为通过在不同的威胁中使用它可以解决这个问题吗?

有什么想法吗?

非常感谢

编辑:

我尝试使用BackgroundWorker。我在我的方法中添加了一个后台工作人员并返回了 ReportProgress。我还在我的主类中添加了一个backgroundWorker,它使用该方法和事件处理程序。然而它不起作用。我对不同的威胁不太熟悉。那我该怎么办呢? 我在这里尝试过:

http://msdn.microsoft.com/ en-us/library/cc221403(VS.95).aspx

I was looking for a way to create a nice progressbar.
I found some code which I used and it worked great if I used a loop. But now I wanted to use it in a real decent application and it gave me a lot of trouble. I have an application where I lookup data on IMDB, so I make a connection to IMDB for for example 500 movietitles, so this takes a while. So I wanted to show a progressbar where the bar grew for each movie it looked up and with some extra info on the movietitle.

I use the following class:

public partial class ProgressDialog : Window, IProgressContext
{
    public ProgressDialog()
    {
        InitializeComponent();
        IconBitmapDecoder ibd = new IconBitmapDecoder(
        new Uri("IMDB.ML.ico", UriKind.RelativeOrAbsolute),
        BitmapCreateOptions.None, BitmapCacheOption.Default);
        this.Icon = ibd.Frames[0];
    }
    public void UpdateProgress(double progress)
    {
        Dispatcher.BeginInvoke(DispatcherPriority.Background,
            (SendOrPostCallback)delegate { Progress.SetValue(ProgressBar.ValueProperty, progress); }, null);
    }

    public void UpdateStatus(string status)
    {
        Dispatcher.BeginInvoke(DispatcherPriority.Background,
            (SendOrPostCallback)delegate { StatusText.SetValue(TextBlock.TextProperty, status); }, null);
    }

    public void Finish()
    {
        Dispatcher.BeginInvoke(DispatcherPriority.Background,
            (SendOrPostCallback)delegate { Close(); }, null);
    }
}

public interface IProgressContext
{
    void UpdateProgress(double progress);
    void UpdateStatus(string status);
    void Finish();
}

This is the imdb lookup method which uses the progressbar, this method uses an already existing xml list so it's only for updating data, not adding new movies:

public static void updateIMDBinfo()
    {

        //initialize progressbar
        ProgressDialog myProgressContext = new ProgressDialog();
        myProgressContext.Show();            

        //load old list
        List<Movie> movieList = XML.getMovieList();

        //create new updated list
        List<Movie> newMovieList = new List<Movie>();
        int count = 1;
        foreach (Movie movie in movieList)
        {
            //update progressbar
            myProgressContext.UpdateProgress((double)count / (double)movieList.Count);
            myProgressContext.UpdateStatus(String.Format("Updating movie: '{0}' ({1}/{2})", movie.Title, count, movieList.Count));

            movie.Link = movie.Link.Substring(movie.Link.IndexOf("http://www.imdb.com/title/") + 26, 9);

            //this creates a new movie where it looks up the data from imdb
            newMovieList.Add(new Movie(movie.Title, movie.Link, movie.Path));

            count++;
        }

        //sort the list
        newMovieList.Sort((Movie m1, Movie m2) => m1.Title.CompareTo(m2.Title));

        //save as xml
        XML.updateMovieList(newMovieList);

        //finish progressbar
        myProgressContext.Finish();
    }

So now when i use the method it opens the progressbar, but the bar never fills, it just keeps adding movies to the list and looking up the updated info without filling the bar. I thought by using it in a different threat would fix this problem?

Any ideas?

Thanks a bunch

Edit:

I tried using the BackgroundWorker. I added a background worker to my method and returned a ReportProgress back. I also added a backgroundWorker to my main class which uses the method, with eventhandlers. It didn't work however. I'm not very familiar with different threats. How should I go about then?
I tried it like in here:

http://msdn.microsoft.com/en-us/library/cc221403(VS.95).aspx

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

如梦亦如幻 2024-08-22 16:00:56

由于你和UI在同一个线程中,所以进度条不会刷新,实际上整个窗口都不会刷新,因为你的操作阻塞了主UI线程。

查看 BackgroundWorker 组件来加载电影列表,它包含您需要的一切。

Since you are in the same thread as the UI, the progress bar does not refresh, in fact the whole window is not refreshed because your operation blocks the main UI thread.

Look at the BackgroundWorker Component to load your movie list, it contains everything you need.

我的痛♀有谁懂 2024-08-22 16:00:56

问题似乎是 updateIMDBinfo 调用占用了您的 UI 线程。请参阅 MSDN 文档了解 Thread 或 ThreadPool 类以启动该进程 - 然后更新进度条的调度可以在 UI 线程上不受阻碍地进行。

我猜现在发生的情况是你的进度条是空的,然后当你完成时突然满了。所有这些调度都排队等待控制从当前消息处理器返回,但它没有返回,因为它与实际工作相关。

It appears that the issue is that the updateIMDBinfo call is tying up your UI thread. See the MSDN docs for the Thread or ThreadPool classes for launching that process -- then the dispatches to update the progress bar can progress unimpeded on the UI thread.

What I would guess is happening now is that your progress bar is empty, and then suddenly full when you're done. All those dispatches are queued up waiting for control to be returned from the current message processor, but the it's not returning because it's tied up with the actual work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文