不确定的进度条 [英] Indeterminate Progress Bar

查看:27
本文介绍了不确定的进度条的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前,我有一个按钮,当用户单击它时,它会查找准备好的特定 CD-ROM 驱动器并包含一个文件.有时,当用户单击按钮时,单击按钮是鼠标按下,程序会挂起不确定的时间,直到计算机读取 CD-ROM 驱动器.

Currently, I have a button that when the user clicks on it, it looks for a specific CD-ROM drive that is ready and contains a file. Sometimes, when the user clicks on a button, the button click is mouse down and the program hangs for an indeterminate time until the computer reads the CD-ROM drive.

我制作了进度条,但我注意到了一些事情:

I made my progress bar but I noticed a few things:

1) 程序在调用检查 cd 驱动器的方法之前挂起/冻结.所以我无法设置进度条在调用方法时显示.当单击按钮并且用户同时放入 CD 时,程序似乎挂起.如何在单击按钮并且鼠标仍然按下/直到系统检测到 CD 驱动器时立即显示进度条?

1) The program hangs/freezes before the method that checks the cd drives gets called. So I can't set the progress bar to display when the method is called. Seems like the program hangs when the button is clicked on and while the user puts in the CD at the same time. How can I display the progress bar as soon as the button is clicked and the mouse is still down/until the system detects the cd drive?

2) 我对如何实现后台工作器感到困惑.我看起来很喜欢这些示例,但没有一个与 MVVM(无代码隐藏)方法匹配的不确定进度条.

2) I'm confused on how to implement Background Worker. I looked liked examples but none of them matched having an indeterminate progress bar with MVVM (No code behind) approach.

3) 如何让操作完成后窗口消失?目前,我有一个取消按钮(绝对没有用).

3) How do I make the window disappear after the operation is done? Currently, I have a cancel button (Definitely not useful).

这是我目前设置的内容.不知道如何继续:

Here's what I have set up so far. Not sure how to continue:

进度条:

<Grid>
        <Border BorderBrush="Black" BorderThickness="2" CornerRadius="4" Background="#EEEEEE" HorizontalAlignment="Left" Height="110" VerticalAlignment="Top" Width="295" />
        <StackPanel>
            <Label x:Name="lblProgress"/>
            <ProgressBar x:Name="progress" Height="25" Width="270"  IsIndeterminate="True" Foreground="Green"></ProgressBar>
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="225,10,0,0" RenderTransformOrigin="0.083,0.526">
                <Button x:Name="btnCancel" Width="60" Content="Cancel" Command="{Binding CloseCommand}"/>
            </StackPanel>
        </StackPanel>
    </Grid>

我有一个 ProgressBarViewModel,其中包含允许用户取消进度窗口的命令.此外,我还有另一个 ViewModel,我需要在里面调用 progressBar Dialog 但我不确定在哪里调用它,因为如果我调用它在我的方法中,按钮仍然挂起而不显示进度条.

I have a ProgressBarViewModel that contains the command that allows the user to cancel the progress window.Also, I have another ViewModel that I need to call the progressBar Dialog inside but I'm not sure where to call it because if I call it inside my method, the button still hangs without displaying a progressbar.

我注意到如果我在代码隐藏中使用 Button_PreviewMouseDown 方法,但是,当鼠标按下并且系统确实显示进度条时进度条会正确显示,但我不想使用代码隐藏,因为我有另一个进度条看法.

I noticed if I use Button_PreviewMouseDown method in codebehind, however, the progress bar appears correctly when the mouse is down and the system does display the progress bar but I don't want to use codebehind because I have the progress bar in another view.

目前,对于我的导入按钮,所附的只是一个调用方法的命令,该方法在驱动器中搜索 CD-ROM 驱动器.

Currently, for my import button, all that is attached is a command that calls a method that searches drives for a CD-ROM drive.

主视图模型:

 public ICommand ImportCDFilePathCommand
        {
            get
            {
                return new RelayCommand(ImportCDFilePath, null);
            }

        }

private void ImportCDFilePath()
        {
           // dialogService.ShowDialog("Progress", progressBarWindow); <---Does not get called until the operation is done


            //Gets all the drives 
            DriveInfo[] allDrives = DriveInfo.GetDrives();

            //checks if any CD-Rom exists in the drives
            var cdRomExists = allDrives.Any(x => x.DriveType == DriveType.CDRom);

            // Get all the cd roms
            var cdRoms = allDrives.Where(x=>x.DriveType==DriveType.CDRom && allDrives.Any(y=>y.IsReady));

 //.... There is other code that is commented out too long and not necessary 

}

一些使用 BackgroundWorker 的尝试:

Some attempts using BackgroundWorker:

static BackgroundWorker _bw = new BackgroundWorker();

//constructor
MainViewModel() {


            _bw.DoWork += bw_DoWork;
            _bw.RunWorkerAsync("Message to worker");
}

 void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            // This is called on the worker thread
            Console.WriteLine(e.Argument);        // writes "Message to worker"
            // Perform time-consuming task...
            ImportCDFilePath();
        }

我得到的错误:

The calling thread must be STA, because many UI components require this.

推荐答案

在 SO WPF Chat 上的 Julien 和 NetSCAPE 的帮助下,我发现了一些我做错的事情:

With the help of Julien and NetSCAPE on SO WPF Chat, I figured out a few things I was doing wrong:

- 我的后台线程中有对话框消息,而在执行后台线程的方法中不应该有这些消息.因此,这就是我不断收到 STA 错误的原因.

-I had dialog messages inside my background thread that should not be there in the method that was executing background threads. Thus, that's why I kept getting the STA error.

-我需要做的就是使用 Task.Run 或 Task.Factory.StartNew 而不是将它们与 await/async 配对,因为它在运行之前等待任务被执行.

-All I needed to do was use Task.Run or Task.Factory.StartNew instead of pairing that with await/async because it was waiting for a task to be executed before running.

以下是我的答案在删除对话框消息后的样子:

Here's how my answer looks now with removed dialog messages:

private void DoSomethingAsync()
{
    ProgressBarVisibility = Visibility.Visible;
    Task.Factory.StartNew(() => { PerformCDDetection(); }).ContinueWith(t => { ProgressBarVisibility = Visibility.Collapsed; });
}

public ICommand ImportFilePathCommand
{
    get
    {
        return new RelayCommand(() => { DoSomethingAsync(); });
    }    
}

private void PerformCDDetection()
{
    //Gets all the drives 
    DriveInfo[] allDrives = DriveInfo.GetDrives();

    //checks if any CD-Rom exists in the drives
    var cdRomExists = allDrives.Any(x => x.DriveType == DriveType.CDRom);

    // Get all the cd roms
    var cdRoms = allDrives.Where(x => x.DriveType == DriveType.CDRom && allDrives.Any(y => y.IsReady));

    if (cdRomExists.Equals(true))
    {
        // Loop through the cd roms collection
        foreach(var cdRom in cdRoms)
        {
            Console.WriteLine("Drive {0}", cdRom.Name);
            Console.WriteLine("  File type: {0}", cdRom.DriveType);

            if (cdRom.IsReady == true)
            {
                if (cdRom.DriveType == DriveType.CDRom)
                {
                    DirectoryInfo di = new DirectoryInfo(cdRom.RootDirectory.Name);

                    var file = di.GetFiles("*.xml", SearchOption.AllDirectories).FirstOrDefault();

                    if (file == null)
                    {
                        Console.WriteLine("failed to find file"); 
                    }
                    else
                    {
                        foreach (FileInfo info in di.GetFiles("*.xml", SearchOption.AllDirectories))
                        {
                            Debug.Print(info.FullName);
                            break;      // only looking for the first one
                        }

                        break;                            
                    }
                }
                else if (cdRom.IsReady == false)
                {
                    Console.WriteLine("Cd-ROM is not ready");
                    break;
                }    
            }
        }
        else
        {
            Console.WriteLine("CD ROM is not detected");
        }    
    }
}

这篇关于不确定的进度条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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