WPF中线程的一个非常基本的解释?

时间:2011-12-29 07:37:48

标签: c# .net wpf multithreading

我对WPF非常新。我在互联网上查看了几个关于线程的示例和教程。他们有自己的描述方式。但是对于像我这样的天真,我想用自己的风格来理解。

我可以使用数据库更新功能开始我的第一次线程化。

以下是该方案:

我要在数据库中插入大量数据。现在让我们假设以下代码(一旦我点击“继续”按钮,这个过程就会启动:

int initial = 0;
int maxData = 10
while (initial<maxData) {
   //Database query here
}

上述过程将在不同的主题中运行。

接下来我在主窗口中有一个“标签”。对于每个数据库查询,我想在标签中显示一些消息。

例如,

// this will happen in default UI thread.
label.Content = "Updating"; // Specifically for @TomTom ;)

编辑: 我做了以下事情:

var task = new Task(() =>
    {
       for (int i=0; i<10; i++) {
          //Create new Grid HERE
          // Add Table with some dynamic data here..
          // print the above Grid here.
        }

    });

task.ContinueWith((previousTask) =>
    {
        label.Content = printerStatus(); // will return "Out of Paper", "printing", "Paper jam", etc.
    },
    TaskScheduler.FromCurrentSynchronizationContext());

label.Content = "Sending to printer";

程序将返回错误,说“调用线程必须是STA,因为许多UI组件都需要这个。”

我不知道下一步该做什么。请帮忙!

3 个答案:

答案 0 :(得分:9)

您需要将BackgroundWorker用于长时间运行的任务,并使用Dispatcher更新之间的UI

 //create background worker
 BackgroundWorker worker = new BackgroundWorker();
 //assign it work
 worker.DoWork += new DoWorkEventHandler(worker_DoWork);
 //start work
 worker.RunWorkerAsync();


//this work will be done in background
void worker_DoWork(object sender, DoWorkEventArgs e)
{
    SET initial = 0;
    SET maxData = 1000
    DO UNTIL initial <1000
   CREATE db query "INSERT INTO (col1,col2,col3) VALUES(value1,value2,value3);"

   //in between your work do this to update label
   label.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,new Action(delegate()
        {
         Label.Content = "SomeValue";
        }
        ));
   END DO
  }

答案 1 :(得分:3)

  1. 多线程无法处理您选择的UI技术(Wpf或Winforms) - 当您必须切换到UI线程来更新控件时,只会略有不同。

    < / LI>
  2. 根据你的代码示例,我必须说,从sql server到你的程序没有回调的可能性。如果你想拥有该功能,你必须在C#中实现循环而不是在sql语句中。

  3. 修改

    根据OP的评论,我添加了一个后台工作示例,并使用TPL (Task Parallel Library)更新前景中的UI:

    var task = new Task(() =>
        {
            // Do something very long ...
        });
    
    task.ContinueWith((previousTask) =>
        {
            label.Content = "Background work has finished.";
        },
        TaskScheduler.FromCurrentSynchronizationContext());
    
    label.Content = "Background work is running.";
    task.Start();
    

答案 2 :(得分:0)

以下是处理WPF线程的示例代码段。

请考虑这种情况。

我们必须从服务器获取一些数据,然后我们才能使用数据。 意味着我们的下一步行动完全取决于任务的回调或完成。

在这种情况下,我们可以使用任务工厂ContinueWith方法,如下面的

ObservableCollection images = new ObservableCollection();
TaskFactory tFactory = new TaskFactory();
tFactory.StartNew(() =>
{
    for (int i = 0; i < 50; i++)
    {
    //GET IMAGE Path FROM SERVER
        System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate()
        {
        // UPDATE PROGRESS BAR IN UI
        });    
    images.Add(("");
    }

}).ContinueWith(t =>
{
    if (t.IsFaulted)
    {
        // EXCEPTION IF THREAD IS FAULT
        throw t.Exception;
    }
    System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate()
    {
        //PROCESS IMAGES AND DISPLAY
    });
});