C#WPF线程监控(如果所有创建的线程都已结束)

时间:2015-04-30 08:19:46

标签: c# wpf multithreading

对于我的项目,我对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回答

3 个答案:

答案 0 :(得分:2)

现在几乎没有理由直接处理线程。使用Task Parallel Libraryasync-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...
    }