C# 线程/任务等待按钮单击

C# 线程/任务等待按钮单击,c#,multithreading,C#,Multithreading,我有一个Windows窗体应用程序,它包含一个与我的应用程序并行运行的任务(System.Thread.Tasks)。这个任务在某种程度上必须等待按钮点击(在主线程中)并从这个按钮捕获数据。 我有一个代码,这是令人惊讶的工作良好。但我相信这不是最好的方法,我想我应该用事件来解决这个问题,但是说实话,我刚刚开始了解事件,所以我还是有点困惑。如果我是对的,请告诉我我能做些什么让它变得更好 下面是我的代码示例: bool BooleanHelper = false; int ButtonData;

我有一个Windows窗体应用程序,它包含一个与我的应用程序并行运行的任务(System.Thread.Tasks)。这个任务在某种程度上必须等待按钮点击(在主线程中)并从这个按钮捕获数据。 我有一个代码,这是令人惊讶的工作良好。但我相信这不是最好的方法,我想我应该用事件来解决这个问题,但是说实话,我刚刚开始了解事件,所以我还是有点困惑。如果我是对的,请告诉我我能做些什么让它变得更好

下面是我的代码示例:

bool BooleanHelper = false;
int ButtonData;

private void MyButton_Click(object sender, EventArgs e) {
   BooleanHelper = true;
   ButtonData = 5; //example      
}

private void MyForm_Shown(object sender, EventArgs e) {
   Task t = Task.Run(()=>{
      while(!BooleanHelper){} //this can't be a good pratice .__.

      // now if the program reaches this line, it means that we can use the ButtonData.
   });
}

有很多线程原语,事件对此很有用

private static ManualResetEvent _continue;
int ButtonData;

private void MyButton_Click(object sender, EventArgs e) {

   ButtonData = 5; //example      
   _ev.Set();
}

private void MyForm_Shown(object sender, EventArgs e) {
   Task t = Task.Run(()=>{
      _continue.Wait(); // there are versions with timeouts as well

      // now if the program reaches this line, it means that we can use the ButtonData.
   });
}

但是我更喜欢其他方法,比如基于参与者的分派。

有很多线程原语,事件对此很有用

private static ManualResetEvent _continue;
int ButtonData;

private void MyButton_Click(object sender, EventArgs e) {

   ButtonData = 5; //example      
   _ev.Set();
}

private void MyForm_Shown(object sender, EventArgs e) {
   Task t = Task.Run(()=>{
      _continue.Wait(); // there are versions with timeouts as well

      // now if the program reaches this line, it means that we can use the ButtonData.
   });
}

但我更喜欢其他方法,如基于参与者的分派。

使用TaskCompletionSource创建一个任务,您可以控制任务何时完成:

TaskCompletionSource<int> buttonTcs = new TaskCompletionSource<int>();

private void MyButton_Click(object sender, EventArgs e)
{
  buttonTcs.SetResult(5);
}

private async void MyForm_Shown(object sender, EventArgs e)
{
  var buttonData = await buttonTcs.Task;

  // now if the program reaches this line, it means that we can use the ButtonData.
}
TaskCompletionSource按钮tcs=new TaskCompletionSource();
私有无效MyButton_单击(对象发送者,事件参数e)
{
按钮。设置结果(5);
}
显示私有异步void MyForm_(对象发送方,事件参数e)
{
var buttonData=等待buttonTcs.Task;
//现在,如果程序到达这一行,这意味着我们可以使用ButtonData。
}

我不知道您的MyForm_中显示的任务是否只是因为您使用了繁忙的等待。如果确实存在需要包装在任务中的长时间运行的内容。请运行,而不仅仅是将等待移动到任务中。

使用TaskCompletionSource创建一个任务,您可以控制任务何时完成:

TaskCompletionSource<int> buttonTcs = new TaskCompletionSource<int>();

private void MyButton_Click(object sender, EventArgs e)
{
  buttonTcs.SetResult(5);
}

private async void MyForm_Shown(object sender, EventArgs e)
{
  var buttonData = await buttonTcs.Task;

  // now if the program reaches this line, it means that we can use the ButtonData.
}
TaskCompletionSource按钮tcs=new TaskCompletionSource();
私有无效MyButton_单击(对象发送者,事件参数e)
{
按钮。设置结果(5);
}
显示私有异步void MyForm_(对象发送方,事件参数e)
{
var buttonData=等待buttonTcs.Task;
//现在,如果程序到达这一行,这意味着我们可以使用ButtonData。
}

我不知道您的MyForm_中显示的任务是否只是因为您使用了繁忙的等待。如果它确实执行了长时间运行的任务,则需要将其包装在任务中。请运行,而不仅仅是将等待移到任务中。

这不是一个好的做法。
-正确,一点也不-除非你喜欢融化你的CPU。我是否正确理解你想在点击按钮后执行任务?@Enigmativity no sr。无论发生什么情况,任务都会执行。在某些情况下,它必须等待按钮单击后才能继续。然后将任务分为两个功能。第一个将自动启动,当它完成时,它将启用该按钮。然后单击按钮时,将调用第二个函数,这将继续执行所有必须执行的操作。@MWsan-您可以使用一些线程信号量来执行此操作-根据Keith的回答-但是这些内容很快就会变得混乱,您很容易难以修复错误。如果您解释您的业务需求是什么,我们会更好地帮助您以更稳健的方式完成这项工作。
这不是一个好做法。
-正确,一点也不-除非你喜欢融化你的CPU。我是否正确理解你想在点击按钮后执行任务?@Enigmativity no sr。无论发生什么情况,任务都会执行。在某些情况下,它必须等待按钮单击后才能继续。然后将任务分为两个功能。第一个将自动启动,当它完成时,它将启用该按钮。然后单击按钮时,将调用第二个函数,这将继续执行所有必须执行的操作。@MWsan-您可以使用一些线程信号量来执行此操作-根据Keith的回答-但是这些内容很快就会变得混乱,您很容易难以修复错误。如果您能解释一下您的业务需求是什么,我们会更好地帮助您以更稳健的方式实现这一点。_ev.Set();这条线是什么?设置事件的信号状态,它允许一个或多个等待线程继续进行。我会考虑将该设置放在单击处理程序的末尾,这样所有数据都可用于工作线程。也可以使用
ManualResetEventSlim
代替
ManualResetEvent
。工作正常。谢谢你;这条线是什么?设置事件的信号状态,它允许一个或多个等待线程继续进行。我会考虑将该设置放在单击处理程序的末尾,这样所有数据都可用于工作线程。也可以使用
ManualResetEventSlim
代替
ManualResetEvent
。工作正常。谢谢