对于我的项目,我对C#和WPF有点新意。我过去在做什么的小图片。我编写了一个程序来备份我的MS SQL数据库。我们的想法是,在它自己的流程线程中启动每个备份过程。这很完美!我使用以下命令启动进程和线程:
...
string db_name = Convert.ToString(dataReader.GetValue(0));
var t = new Thread(() => BackupProcess(ServerName, SQLinstance, BackupPath, db_name));
t.Start();
现在,当一切都结束时,我想像“如果最后一个线程结束,而不是像XY这样的东西”监视 这样做的最佳方式是什么? THX回答
答案 0 :(得分:2)
现在几乎没有理由直接处理线程。使用Task Parallel Library和async-await非常容易。
您可以启动任务数量,保留任务的引用,并在需要时等待/等待它。
Task backupTask = Task.Run(() => BackupProcess(ServerName, SQLinstance, BackupPath, db_name));
Task someOtherTask = Task.Run(() => SomeOtherWork(anyParameter));
...
//Later at some point
await Task.WhenAll(new []{backupTask, someOtherTask });
//At this point all tasks has been completed
//Do whatever you need to execute after all tasks finished
注意:BackupProcess
如果使用asynchronous API of your data provider而不使用Task.Run
而使ThreadPool线程在那里等待,则可以使CountDownEvent
异步。
如果你仍然想要使用线程方法(你不应该这样做),你可以使用Thread.Join
进行同步,或者ObservableCollection<Model> collection = new ObservableCollection<Model>();
ObservableCollection<Model> filteredCollection = new ObservableCollection<Model>(from item in collection where item.ID >0 && item.ID < 10 orderby item.ID select item);
使用所有已启动的线程。
答案 1 :(得分:0)
看看TPL和ContinueWith。它非常优雅,应符合您的要求。
Action<string> action =
(str) =>
Console.WriteLine("Task={0}, str={1}, Thread={2}", Task.CurrentId, str, Thread.CurrentThread.ManagedThreadId);
// Creating a sequence of action tasks (that return no result).
Console.WriteLine("Creating a sequence of action tasks (that return no result)");
Task.Factory.StartNew(() => action("alpha"))
.ContinueWith(antecendent => action("beta")) // Antecedent data is ignored
.ContinueWith(antecendent => action("gamma"))
.Wait();
来自:https://msdn.microsoft.com/de-de/library/dd321405(v=vs.110).aspx
ContinueWith()也可以帮助您处理执行任务时发生的异常。
答案 2 :(得分:0)
好的,我真的不明白它的方式。正如您所看到的,我将在Point中的Loop中开始一个新任务:&#34; while(dataReader.Read())&#34;。我的服务器中有尽可能多的数据库,循环将重复。我不知道下次我将拥有多少个DB。最后,当所有任务完成后,我想转到&#34; DoSomething&#34;方法。有没有人可以告诉我它的方式。这让我很疯狂(这个东西)。 : - )
private async void ReadDatabase()
{
string errorMSG01 = "...";
string errorMSG02 = "...";
string captionMSG = "...
string BackupPath = txtBakPath.Text;
string ServerName = txtSqlServer.Text;
string SQLinstance = cmbSqlInst.SelectedItem.ToString();
MessageBoxButtons buttons = MessageBoxButtons.OK;
if (String.IsNullOrEmpty(txtBakPath.Text))
{
System.Windows.Forms.MessageBox.Show(errorMSG01, captionMSG, buttons, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
}
else if (!Directory.Exists(BackupPath))
{
System.Windows.Forms.MessageBox.Show(errorMSG02, captionMSG, buttons, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
}
else
{
string connetionString = null;
SqlConnection connection;
SqlCommand command;
string sql = null;
SqlDataReader dataReader;
connetionString = ("Data Source=DPC-OHEINRICH\\NETZWERKLABOR; Integrated Security=True;");
sql = "Select * from Sys.Databases";
connection = new SqlConnection(connetionString);
try
{
connection.Open();
command = new SqlCommand(sql, connection);
dataReader = command.ExecuteReader();
StatusPrinter(0x0003, null);
CreateLogfile(BackupPath);
DeleteOldBakFiles();
while (dataReader.Read())
{
string db_name = Convert.ToString(dataReader.GetValue(0));
Task backupTask = Task.Run(() => BackupProcess(ServerName, SQLinstance, BackupPath, db_name));
}
dataReader.Close();
command.Dispose();
connection.Close();
}
catch (Exception ex)
{
lblStatusMessage.Content = Convert.ToString(ex.Message);
}
}
}
private void BackupProcess(string ServerName, string SQLinstance, string BackupPath, string db_name)
{
DateTime today = DateTime.Now;
string todayformat = string.Format("{0:G}", today);
string BakFileDate = todayformat.Replace(".", "").Replace(" ", "").Replace(":", "");
string ReportBakFile = BackupPath + "\\" + db_name + "_db_" + BakFileDate + @".bak'";
if (db_name != "tempdb")
{
string connetionString = null;
SqlConnection connection;
SqlCommand command;
string sql = null;
SqlDataReader dataReader;
connetionString = ("Data Source="+ServerName+"\\"+SQLinstance+"; Integrated Security=True;");
sql = @"BACKUP DATABASE " + db_name + @" TO DISK = '" + BackupPath + "\\" + db_name + "_db_" + BakFileDate + @".bak'";
connection = new SqlConnection(connetionString);
try
{
connection.Open();
command = new SqlCommand(sql, connection);
dataReader = command.ExecuteReader();
dataReader.Close();
command.Dispose();
connection.Close();
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
this.Dispatcher.Invoke(new Action(() => this.WriteLogile(1, ReportBakFile)));
this.Dispatcher.Invoke(new Action(() => this.StatusPrinter(0x0004, db_name)));
}
}
public void DoSomething()
{
//we are done...
}