后台工作程序以更新列表视图中的多个项目

我正在尝试使用此方法更新列表框中的多个值:此方法的作用是复制指定目录的内容,但它将当前文件名输出到后台工作进程更改事件.

private bool CopyDirectory(string SourcePath, string DestinationPath, bool Recursive, BackgroundWorker worker, DoWorkEventArgs e)
    {
        List<string> Paths = new List<string>();
        List<string> Files = new List<string>();

        //for windows xp My documents
        if(!Directory.Exists(SourcePath))
        {
            SourcePath = SourcePath.Replace(@"C$\Users\", @"C$\Documents and Settings");

            int doccount = Regex.Matches(SourcePath, "Documents").Count;

            //if source contains 2 documents
            if(doccount > 1)
            {
                ReplaceLastOccurrence(SourcePath, "Documents", "My Documents");
            }
        }


        //set file permissions
        FileIOPermission f2 = new FileIOPermission(FileIOPermissionAccess.Read, SourcePath);
        f2.AllLocalFiles = FileIOPermissionAccess.Read;

        f2.Demand();

        foreach (string StringPath in DirectoryList(SourcePath, Recursive, null))
            Paths.Add(StringPath);
        foreach (string StringPath in FileList(SourcePath, Recursive, null))
            Files.Add(StringPath);
        try
        {

            foreach (string dirPath in Paths)
                System.IO.Directory.CreateDirectory(dirPath.Replace(SourcePath, DestinationPath));
            foreach (string newPath in Files)
            {



                string[] filename = newPath.Split('$');

                string currentfile = "C:" + filename[1];

                //report the file name to the background worker
                worker.ReportProgress(0, currentfile);


                System.IO.File.Copy(newPath, newPath.Replace(SourcePath, DestinationPath), Recursive);




            }
            return true;
        }
        catch { return false; }
    }




    private static List<string> FileList(string RootDirectory,
        bool SearchAllDirectories, Predicate<string> Filter)
    {
        List<string> retList = new List<string>();

        try
        {
            List<string> DirList = new List<string> { RootDirectory };

            if (SearchAllDirectories)
                DirList.AddRange(DirectoryList(RootDirectory, SearchAllDirectories, Filter));

            foreach (string DirectoryStr in DirList)
            {
                DirectoryInfo di = new DirectoryInfo(DirectoryStr);
                try
                {
                    foreach (FileInfo FileStr in di.EnumerateFiles())
                    {
                        try
                        {
                            if ((Filter == null) || (Filter(FileStr.FullName)))
                                retList.Add(FileStr.FullName);
                        }

                        catch (Exception) { }
                    }
                }
                catch (UnauthorizedAccessException) { }
                catch (Exception) { }
            }
        }
        catch (Exception) { }
        return retList;
    }

    private static List<string> DirectoryList(string RootDirectory,
        bool SearchAllDirectories, Predicate<string> Filter)
    {
        List<string> retList = new List<string>();
        try
        {
            DirectoryInfo di = new DirectoryInfo(RootDirectory);

            foreach (DirectoryInfo DirectoryStr in di.EnumerateDirectories())
            {
                try
                {
                    if ((Filter == null) || (Filter(DirectoryStr.FullName)))
                    {
                        retList.Add(DirectoryStr.FullName);

                        if (SearchAllDirectories)
                            retList.AddRange(DirectoryList(DirectoryStr.FullName, SearchAllDirectories,
                                Filter));
                    }
                }
                catch (UnauthorizedAccessException) { }

                catch (Exception) { }
            }
        }
        catch (Exception) { }
        return retList;
    }

这仅适用于一个文件名更新,但是,我的程序将对导演进行多次复制,这些导演希望更新列表视图项以将其显示给用户.

private void bgwBackup_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        this.InvokeEx(c => this.lblBackupStatus.Text = e.UserState.ToString());
    }

我的问题是如何用指定路径的当前文件名更新多个listviewitems?如果需要,我可以发布我的工作处理程序.谢谢.

EDIT1这是我要求的DO_WORK:

  private void bgwBackup_DoWork(object sender, DoWorkEventArgs e)
    {

        //Textbox Array Values
        // 0 = computername
        // 1 = username
        // 2 = password
        string[] tbvalues = (string[])e.Argument;


        string computer = tbvalues[0];
        string user = tbvalues[1];
        string pass = tbvalues[2];






        try
        {
            //AD SEARCH

            DirectoryEntry de = new DirectoryEntry("WinNT://" + Environment.UserDomainName + "/" + user);
            string homepath = de.Properties["homedirectory"].Value.ToString();

            if (string.IsNullOrWhiteSpace(homepath))
            {
                //do something when home drive is missing
                MessageBox.Show("NO H DRIVE");
            }

            else
            {

                //Declare strings 
                string os = GetOsName(computer);

                string desktop="";
                    string documents="";
                        string favorites="";

                        string outlooksig = "";
                        string outlookcache = "";


                        string hdriveroot = homepath + @"\PKBACKUP " + DateTime.Now.ToString("MM-dd-yyyy--hh-mm-ss");

                        string hudp = hdriveroot + @"\Desktop";
                        string hudoc = hdriveroot + @"\Documents";
                        string hufav = hdriveroot + @"\Favorites";
                        string hprintdir = hdriveroot + @"\printers\";
                        string outlooksigdir = hdriveroot + @"\Outlook Files\Signatures";
                        string outlookcachedir = hdriveroot + @"\Outlook Files\Cache";






                if (os.Contains("XP"))
                {
                    desktop = @"\\" + computer + @"\C$\Documents and Settings\" + user + @"\Desktop";
                    documents = @"\\" + computer + @"\C$\Documents and Settings\" + user + @"\My Documents";
                    favorites = @"\\" + computer + @"\C$\Documents and Settings\" + user + @"\Favorites";

                    //outlook signatures
                    outlooksig = @"\\" + computer + @"\C$\Documents and Settings\" + user + @"\Application Data\Microsoft\Signatures";

                    //outlook cache
                    outlookcache = @"\\" + computer + @"\C$\Documents and Settings\" + user + @"\Application Data\Microsoft\Outlook";

                }


                else

                {
                    desktop = @"\\" + computer + @"\C$\Users\" + user + @"\Desktop";
                    documents = @"\\" + computer + @"\C$\Users\" + user + @"\Documents";
                    favorites = @"\\" + computer + @"\C$\Users\" + user + @"\Favorites";
                    outlooksig = @"\\" + computer + @"\C$\Users\" + user + @"\AppData\Roaming\Microsoft\Signatures";
                    outlookcache = @"\\" + computer + @"\C$\Users\" + user + @"\AppData\Roaming\Microsoft\Outlook";


                }










                //Copy Files 
                using (new Impersonator(user, "Domain.org", pass))
                {

                   string outlookext = "nk2";

                    CopyDirectory(favorites, hufav, true, bgwBackup, e);
                   CopyDirectory(documents, hudoc, true, bgwBackup, e);
                    CopyDirectory(desktop, hudp, true, bgwBackup, e);
                    CopyDirectory(outlooksig, outlooksigdir, true, bgwBackup, e); 
                    copybyext(outlookcache, outlookcachedir, outlookext, user); //copy nk2 file method







                    //Printers 
                    List<string> printers = new List<string>();

                        foreach (string printername in lbBackupprinters.Items)
                        {
                            if (printername.Contains("No Printers Found"))
                            {
                                //Add listview entry that no printers were found
                            }

                            else
                            {
                                if (Directory.Exists(hprintdir) == false)
                                {
                                    Directory.CreateDirectory(hprintdir);
                                }

                            string prntsvr;
                            string printer;

                            //strip out numbers in string
                            prntsvr = Regex.Replace(printername, "[^0-9]+", string.Empty);

                            //take the first number in the string
                            prntsvr = prntsvr[0].ToString();

                            //remote everything before last comma
                            printer = printername.Substring(printername.LastIndexOf(',') + 1);

                            //add vbs to printer name
                            printer = printer + ".vbs";

                            //get file path of printer vbs script
                            string[] printerpaths = Directory.GetFiles(@"\\dist-win-prnt-" + prntsvr + @"\printerscripts", printer);

                            //append string builder with print server path

                            if (!File.Exists(printerpaths[0]))
                            {
                                //do something if the printer does not exist, add error. 

                            }

                            else
                            {
                                printers.Add(printerpaths[0]);
                            }

                        }

                        string defaultprinter = lbBackupprinters.Items[0].ToString() + ".vbs";
                        defaultprinter = defaultprinter.Substring(defaultprinter.LastIndexOf(',') + 1);
                        //
                        //Download printer vbs script(s)
                        foreach (string printstring in printers)
                        {

                            string hprintfilename = printstring.Substring(printstring.LastIndexOf("\\") + 1);




                            if (hprintfilename.Equals(defaultprinter))
                            {


                                File.Copy(printstring, hprintdir +  "(Defualt) "+ hprintfilename, true);

                            }

                            else
                            {



                                File.Copy(printstring, hprintdir + hprintfilename, true);
                            }

                        }

                    } // end else





                }
            }

        } //end try

        catch (Win32Exception logonfail)
        {

            MessageBox.Show("LOGON FAIL" + logonfail);

            //add label for failure
            return;

        }

        catch (DirectoryServicesCOMException adfail)
        {
            MessageBox.Show(adfail.ToString());
        }

        catch (UnauthorizedAccessException accessex)
        {
            MessageBox.Show(accessex.ToString());
        }






    }

EDIT2:程序的图像

EDIT3:这是我的进度已更改并完成的代码

      //this only updates the status text and does not update the listview control. 
    private void bgwBackup_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        this.InvokeEx(c => this.lblBackupStatus.Text = e.UserState.ToString());
    }

    private void bgwBackup_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        lblBackupStatus.Text = "Backup job completed";
    }`

解决方法:

首先,添加另一个类

class BackupTask
{
    public string MachineName { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string CurrentFile { get; set; }
    public int OverallProgress { get; set; }
}

然后

private List<BackupTask> task_definitions = new List<BackupTask>();  //this is needed to parallel foreach 
private List<BackupTask> tasks = new List<BackupTask>();  //this is what you will use to report progress of your copying 

并假设您的背景工作人员名为“ bw”

私人BackgroundWorker bw;

将此添加到您的XAML文件(在主网格之前)

<Window.Resources>
    <DataTemplate x:Key="BackupTask">            
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding MachineName}" Margin="2,4,2,4"/>
            <TextBlock Text="{Binding Username}" Margin="2,4,2,4" />
            <TextBlock Text="{Binding Password}" Margin="2,4,2,4"/>
            <TextBlock Text="{Binding CurrentFile}" Margin="2,4,2,4"/>
            <TextBlock Text="{Binding OverallProgress}" Margin="2,4,2,4"/>
        </StackPanel>
    </DataTemplate>
</Window.Resources>

在您的列表视图中设置ItemTemplate =“ {StaticResource ResourceKey = BackupTask}

所以在窗口构造器中

bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);

您的按钮

private void btn_AddToQueue_Click(object sender, RoutedEventArgs e)
{
    BackupTask bt = new BackupTask();
    bt.MachineName = //load these
    bt.Username = // from your 
    bt.Password = //textboxes
    bt.CurrentFile = "";
    bt.OverallProgress = 0;
    AddOrModifyTask(bt);    
    listView1.ItemsSource = tasks;
}


private void btn_StartBackup_Click(object sender, RoutedEventArgs e)
{
    if (!bw.IsBusy)
        bw.RunWorkerAsync();
}

当然,您还需要

void AddOrModifyTask(BackupTask t)
{
    bool found = false;
    foreach (BackupTask bt in tasks)
    {
        if (bt.MachineName == t.MachineName)
        {
            found = true;
            bt.CurrentFile = t.CurrentFile;
            bt.OverallProgress = t.OverallProgress;
        }
    }
    if (!found)
        tasks.Add(t);
}

您的进度栏事件

void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    lock (tasks)
    {
        AddOrModifyTask((BackupTask)e.UserState);
    }
    listView1.ItemsSource = tasks;
    listView1.Items.Refresh();
}


void bw_DoWork(object sender, DoWorkEventArgs e)
{
    task_definitions = tasks;
    Parallel.ForEach(task_definitions, task =>
        {
            string computer = task.MachineName;
            string user = task.Username;
            string pass = task.Password;
            //your old Do_Work code
        });
}

而不是将后台工作程序作为参数传递,而是传递关联的BackupTask对象,并始终使用bw

快速工作示例是here

上一篇:C#.Net-如何取消BackgroundWorker从WebService提取数据


下一篇:C#backgroundworker RunworkerCompleted与异步等待