后台工作程序以更新列表视图中的多个项目
作者:互联网
我正在尝试使用此方法更新列表框中的多个值:此方法的作用是复制指定目录的内容,但它将当前文件名输出到后台工作进程更改事件.
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
标签:listview,backgroundworker,c 来源: https://codeday.me/bug/20191030/1970667.html