C# WPF BackgroundWorker执行

C# WPF BackgroundWorker执行,c#,wpf,multithreading,C#,Wpf,Multithreading,我已经编写C#有一段时间了(我是计算机科学专业的学生),从来没有实现过线程 我目前正在为一个客户端构建一个应用程序,该客户端需要线程来执行一系列操作 由于客户/提供商协议的性质,我无法发布我正在使用的源代码。我发布的代码是一般形式的。基本上是我实现的基本思想,不包括特定于内容的源代码 第一个片段演示了我的基本结构 Progress类是一个自定义进度窗口,显示为对话框以防止用户UI交互 我目前正在使用该代码根据应用程序代码另一个区域中的对象集合完成数据库调用 例如,我有一个自定义类的“对象”集合,

我已经编写C#有一段时间了(我是计算机科学专业的学生),从来没有实现过线程

我目前正在为一个客户端构建一个应用程序,该客户端需要线程来执行一系列操作

由于客户/提供商协议的性质,我无法发布我正在使用的源代码。我发布的代码是一般形式的。基本上是我实现的基本思想,不包括特定于内容的源代码

第一个片段演示了我的基本结构

Progress类是一个自定义进度窗口,显示为对话框以防止用户UI交互

我目前正在使用该代码根据应用程序代码另一个区域中的对象集合完成数据库调用

例如,我有一个自定义类的“对象”集合,我代表这些自定义类执行这些数据库调用。当我一次且仅一次调用“GeneraledFunction”时,我当前的设置工作正常

我需要做的是为集合中的每个对象调用此函数一次。我试图使用foreach循环来遍历集合,然后尝试了for循环

对于这两个循环,结果是相同的。异步操作的执行完全符合集合中第一个项的要求。然而,这是它唯一的作用。对于每个后续项目,将显示进度框(我的自定义窗口)并立即关闭

就数据库调用而言,对集合中第一项的调用是唯一成功完成的调用。其他的都没有尝试过

我已经尝试了所有我知道和不知道做的事情,但我似乎无法让它发挥作用

我怎样才能让它在我的整个收藏中发挥作用

非常感谢您的任何帮助

Progress progress;

BackgroundWorker worker;

// Cancel the current process
private void CancelProcess(object sender, EventArgs e)
{
 worker.CancelAsync();
}

// The main process ... "Generalized"
private void GeneralizedFunction()
{
 progress = new Progress();
 progress.Cancel += CancelProcess;
 progress.Owner = this;

 Dispatcher pDispatcher = progress.Dispatcher;

 worker = new BackgroundWorker();
 worker.WorkerSupportsCancellation = true;

 object[] workArgs = { arg1, arg2, arg3};

 worker.DoWork += delegate(object s, DoWorkEventArgs args)
 {
  /* All main logic here

  */

  foreach(Class ClassObject in ClassObjectCollection)
  {
   //Some more logic here

   UpdateProgressDelegate update = new UpdateProgressDelegate(updateProgress);

   pDispatcher.BeginInvoke(update, arg1,arg2,arg3);
   Thread.Sleep(1000);
  }
 };
 worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
 {
  progress.Close();
 };

 worker.RunWorkerAsync(workArgs);
 progress.ShowDialog();
}

public delegate void UpdateProgressDelegate(arg1,arg2,arg3);

private void updateProgress(arg1,arg2,arg3)
{
 //Update progress
}

好的,那么您在DoWork处理程序中运行了一个后台进程。该线程生成许多其他线程(使用BeginInvoke),然后休眠1秒。(为什么要睡(1000)?)

似乎没有人试图在for循环之后等待UpdateProgressDelegate线程完成。因此,您将调用
progress.Close()当某些PDispatcher仍在执行时

我也看不到Bgw和对话框之间的任何通信

这里的快速修复方法不是在循环中调用BeginInvoke,而是在bgw线程中执行所有逻辑。首先,让它发挥作用。还有一个提示:真正的程序不会睡眠

然后,如果你想产生更多的线程,你需要实现一些rendez-vous逻辑。使用EventWaitHandle类或其他什么


请注意,在.NET4(使用Parallel.ForEach)中,这将变得非常容易。

好的,因此您可以在DoWork处理程序中运行一个后台进程。该线程生成许多其他线程(使用BeginInvoke),然后休眠1秒。(为什么要睡(1000)?)

似乎没有人试图在for循环之后等待UpdateProgressDelegate线程完成。因此,您将调用
progress.Close()当某些PDispatcher仍在执行时

我也看不到Bgw和对话框之间的任何通信

这里的快速修复方法不是在循环中调用BeginInvoke,而是在bgw线程中执行所有逻辑。首先,让它发挥作用。还有一个提示:真正的程序不会睡眠

然后,如果你想产生更多的线程,你需要实现一些rendez-vous逻辑。使用EventWaitHandle类或其他什么


请注意,在.NET 4中(使用Parallel.ForEach),这变得非常容易。

progress.Close()
上设置一个断点,以查看是否正在调用它(导致进度窗口消失)。您可能需要调用
DispatcherOperation.Wait()
,以确保在所有异步工作完全完成之前,DoWork()不会退出。BeginInvoke()返回DispatcherOperation—您需要使用它加入线程并等待它们完成


您可能需要保留所有调用的Dispatcher操作的列表(pDispatcher.BeginInvoke(update,arg1,arg2,arg3))。在foreach循环之后,您只需等待每个循环完成。我假设问题是RunWorkerCompleted正在启动,因为您没有等待Dispatch操作完成(从而关闭进度窗口)。

progress.Close()
上设置断点,查看是否正在调用它(导致进度窗口消失)。您可能需要调用
DispatcherOperation.Wait()
,以确保在所有异步工作完全完成之前,DoWork()不会退出。BeginInvoke()返回DispatcherOperation—您需要使用它加入线程并等待它们完成


您可能需要保留所有调用的Dispatcher操作的列表(pDispatcher.BeginInvoke(update,arg1,arg2,arg3))。在foreach循环之后,您只需等待每个循环完成。我假设问题是RunWorkerCompleted正在启动,因为您没有等待Dispatch操作完成(从而关闭进度窗口)。

请澄清:上面代码示例中的
foreach
循环是否按预期工作?或者是否有一个外部循环重复调用
GeneralizedFunction
?带有取消的简单WPF进度窗口请澄清:上面代码示例中的
foreach
循环按预期工作?或者是否有一个外部循环反复调用
GeneralizedFunction
?简单的WPF进度窗口取消我想你读错了,每个
BackgroundWorker
都有一个
new
进度对话框,每个worker在完成工作和关闭进度之前都会循环所有内容。@Aviad,您可能是对的,但我看到DoWork()内的循环中有一个BeginInvoke。但真正的问题可能是数据库的东西(未显示)。我认为你读错了,有一个新的