Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何让程序等待任务完成,然后在单击关闭按钮后退出_C#_Multithreading - Fatal编程技术网

C# 如何让程序等待任务完成,然后在单击关闭按钮后退出

C# 如何让程序等待任务完成,然后在单击关闭按钮后退出,c#,multithreading,C#,Multithreading,正如标题所示,如何让我的程序等待完成某件事情,然后在单击close按钮后退出 我必须确保一些重要任务已经完成,这样我才能让程序退出。但是我不知道怎么做 我试图创建一个这样的标志: public partial class MainForm : Form { public bool closeable = true; public MainForm() { InitializeComponent();

正如标题所示,如何让我的程序等待完成某件事情,然后在单击close按钮后退出

我必须确保一些重要任务已经完成,这样我才能让程序退出。但是我不知道怎么做

我试图创建一个这样的标志:

public partial class MainForm : Form
    {
        public bool closeable = true;
        public MainForm()
        {
            InitializeComponent();
        }
         public setCloseable()
         {
             this.closeable = false;
         }
    }
在另一个线程中,当我的程序正在做一些非常重要的事情时,我在任务完成后将“closeable”设置为false,将closeable设置为true; 当使用按钮单击关闭按钮时,我使用以下代码:

private void MainForm_closing(object sender, FormClosingEventArgs e)
    {
        if (this.closeable == true)
        {
            Application.Exit();
        }
    }
这不起作用,因为如果使用时该值不为真,请单击“关闭”。然后程序将不会关闭

这条路对吗?我应该如何改进它或提出任何建议?

您可以使用该属性。将其设置为
true
将取消关闭表单

bool hasUserClickedClose = false;
private void MainForm_closing(object sender, FormClosingEventArgs e)
{
    if (!this.closeable)
    {
        e.Cancel = true; 
        hasUserClickedClose = true;
    }
}
然后在其他方法完成其任务之后

if(hasUserClickedClose)
{
   this.closeable = true;
   Application.Exit();
}

保持代码不变,但必须在关闭处理程序中将
FormClosingEventArgs.Cancel
分配给
True
,以避免程序在不应该关闭时关闭

您应该在结束处理程序中添加一个
计时器
,该计时器仅在您正在运行任务且任务尚未启动时启动。这个计时器每秒钟或五秒钟运行一次,或者任何你认为合适的时间。计时器的任务是检查任务是否已完成,如果已完成,它会将
closeable
字段设置为true,并在程序中触发
Close
事件

然后,您的
FormClosing
事件将触发,查看
closeable
是否为
True
,然后它将不会将
FormClosingEventArgs.Cancel
设置为True,并允许程序退出

Timer timer1 = null;
public MainForm()
{
    InitializeComponent();

    timer1 = new Timer();
    timer1.Interval = (int)new TimeSpan(0, 0, 4).TotalMilliseconds;
    timer1.Tick += (s, ev) => { timer1.Stop();  closeable = IsTaskDone(); Close(); };
}

public bool closeable = true;
public void setCloseable()
{
    this.closeable = false;
}

private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
    if (this.closeable == true)
    {
        Application.Exit();
    }
    else
    {
        timer1.Start();

        e.Cancel = true;
    }
}

private bool IsTaskDone()
{
    // TODO: returns true if the task is completed
}

键盘输入法是正确的,我认为它也是最简单的。然而,我怀疑你在期待更聪明的东西

您可以创建一个特殊的单例类。在MainForm中使用“closeable”标志,而只需放置一个integer类型的“ImportantTaskScont”

每次重要任务启动时,您都应该递增该计数器,并在任务终止时递减该计数器

singleton模式简化了从任何地方对控制器实例的访问

现在,这里是诀窍:

// Winforms/WPF version
public sealed class CloseManager
{
  private CloseManager(){}
  private static CloseManager _instance;
  public static CloseManager Instance
  {
    get 
    { 
      if (_instance == null) _instance = new CloseManager();
      return _instance;
    }
  }


  private static bool closeable;
  private static int importantTasksCount;

  public static void CloseRequest()
  {
    this.closeable = true;
  }

  public static void IncImportantTask()
  {
    this.importantTasksCount++;
  }

  public static void DecImportantTask()
  {
    this.importantTasksCount--;
    if (this.closeable) Application.Exit();
  }

}

您可以在
importantTask
任务中完成繁重的工作,但从用户的角度来看,这样做有点难看。根据你所说的你想要的,这应该是可行的:

public partial class MainForm : Form
 {
    public MainForm()
    {
        InitializeComponent();
        this.importantTask= Task.Factory.StartNew(()=>{/*do your work*/});
    }
    private Task importantTask;

    private async void MainForm_closing(object sender, FormClosingEventArgs e)
    {
         await importantTask;
    }
}


你可以使用backgroundworker,也可以使用task和eventwaithandles。如何,你能给我一些演示吗?这里是backgroundworker,这里是eventwaithandles,你可以将TPL与WaitAll一起使用。所有这些只是让程序在有重要任务时无法关闭。我需要它在任务完成后退出!我以为这就是重点?您不希望应用程序在执行重要工作时关闭,但应在该任务完成时关闭。随着代码的运行,此任务完成后,应再次单击关闭!我不想再次单击“关闭”按钮。如果用户单击“关闭”按钮,然后在方法完成后检查此变量,您能否只设置一个变量?太好了,我怎么能不考虑计时器!哈哈,太好了,我想开始一个新的线程。但你解决了我的问题。想了很多!但请稍候,当使用“单击关闭”时,也可能发生这种情况。任务正在运行,当任务不幸完成时,新任务再次启动,更糟糕的是,当计时器检查可关闭项时,它为false,但当任务完成时,计时器未检查。。。。。。。。哇,一个糟糕的情况。我个人不喜欢计时器的方式,也因为计时器和窗口在没有正确管理的情况下可能会导致内存泄漏。让我们说,上面的一个是非常具体的情况下,但只是在案件有更多的窗口,你会得到一个痛苦…顺便说一句。现在我有另一个类。在这个类中,我想设置closeable而不使用新的MainForm如何实现?@JasonYang,我已经更新了我的代码示例。这将更好地观察新任务的启动。此外,您还可以缩短间隔。谢谢,但是这段代码很难阅读。而且重要的任务不仅仅是一项。因此,我认为这不是一个好的解决方案。但再次感谢为什么要使用单例模式?我建议使用单例模式,因为请求的函数是全局函数(即退出应用程序),并且很容易从应用程序中的任何位置访问。用户没有指定负责“重要”任务的人,因此单身者应该是相当中立的。此外,我不知道只有一个主窗体:一个应用程序可能打开多个窗口。你的代码似乎不是一个单例。你能再次编辑它吗?这个类或者至少计数器字段不应该是静态的吗?好吧,我明白了:我的示例提到了WPF,但在Winforms世界中没有什么不同。让我编辑源代码。。。