简体   繁体   English

按下按钮后的while循环功能并在按下另一个按钮时停止循环C#

[英]While Loop Function after a button is pressed and stop looping when another button is pressed C#

In my Windorm Form application, I have two buttons which a loop function will begin to do the work when button1 is pressed and stop executing after button2 is pressed.在我的 Windorm Form 应用程序中,我有两个按钮,当按下按钮 1 时循环函数将开始工作,并在按下按钮 2 后停止执行。 How could i do this to prevent my GUI from non-responsive.我怎么能这样做来防止我的 GUI 无响应。 How could i insert command while(button2.clicked != true)我怎么能插入命令while(button2.clicked != true)

My code for button 1:我的按钮 1 代码:

private async void EmoStart_Click_1(object sender, EventArgs e)
    {
        //var repeat = "true";
        string imageFilePath = "C:\\Users\\Administrator\\source\\repos\\FaceDetection\\FaceDetection\\test3.jpg";
       while (VoiceStart_Click_2 != "true")
       {
        var image = pictureBox1.Image;
        image = resizeImage(image, new Size(1209, 770));
        image.Save(imageFilePath);
        if (File.Exists(imageFilePath))
        {
            var Emo = await FaceEmotion.MakeAnalysisRequest(imageFilePath);
            if (Emo[0].FaceAttributes.Emotion.Anger >= 0.5)
            {
                EmoBox.Text = "Anger, Bad Driving Condition, Soft Music will be played";
            }
            else if (Emo[0].FaceAttributes.Emotion.Contempt >= 0.5)
            {
                EmoBox.Text = "Contempt, Bad Driving Condition, Soft Music will be played";
            }
            else if (Emo[0].FaceAttributes.Emotion.Disgust >= 0.5)
            {
                EmoBox.Text = "Disgust, Bad Driving Condition, Soft Music will be played";
            }
            else if (Emo[0].FaceAttributes.Emotion.Fear >= 0.5)
            {
                EmoBox.Text = "Fear, Bad Driving Condition, Soft Music will be played";
            }
            else if (Emo[0].FaceAttributes.Emotion.Happiness >= 0.5)
            {
                EmoBox.Text = "Happiness, Good Driving Condition";
            }
            else if (Emo[0].FaceAttributes.Emotion.Neutral >= 0.5)
            {
                EmoBox.Text = "Neutral, Good Driving Condition";
            }
            else if (Emo[0].FaceAttributes.Emotion.Sadness >= 0.5)
            {
                EmoBox.Text = "Sadness, Bad Driving Condition, Rock Music will be played";
            }
            else if (Emo[0].FaceAttributes.Emotion.Surprise >= 0.5)
            {
                EmoBox.Text = "Happiness, Bad Driving Condition, Soft Music will be played";
            }
            else
            {
                EmoBox.Text = "Stable Condition, Good Driving Condition";
            }
        }
    }

While for my button2 code:而对于我的 button2 代码:

private async void VoiceStart_Click_2(object sender, EventArgs e)
{
    string command = await Voice.RecognizeSpeechAsync();
    VoiceBox.Text = command;
}

Thank you!谢谢!

You have to run your loop in a separate thread.您必须在单独的线程中运行循环。 For example, you can run it asynchroniously.例如,您可以异步运行它。 Something like this:像这样的东西:

// start the loop
private async void button1_Click(object sender, EventArgs e)
{
    LoopStopped = false;
    await StartLoopAsync();
}

// put yor while loop here
private Task StartLoopAsync()
{
    return Task.Run(() =>
    {
        while (LoopStopped == false)
        {
            var date = DateTime.Now;
            System.Diagnostics.Debug.WriteLine(date);

        }
        System.Diagnostics.Debug.WriteLine("Thread stopped.");
    });
}

// stop the loop
private void button2_Click(object sender, EventArgs e)
{
    LoopStopped = true;
}

Where LoopStopped is global boolean variable.其中LoopStopped是全局布尔变量。

All the operations you put into the EmoStart_Click_1 is running synchronously , except:您放入EmoStart_Click_1所有操作都是同步运行的,除了:

FaceEmotion.MakeAnalysisRequest(imageFilePath)

thus the interface (UI) is frozen.因此界面(UI)被冻结。

It is not enough to change the signature of the method to async as you did.像您那样将方法的签名更改为异步是不够的。 You must tell the compiler, which other parts should be awaited.您必须告诉编译器应该等待哪些其他部分。 You want your whole while function async!你想要你的整个 while 函数异步!

private async void EmoStart_Click_1(object sender, EventArgs e)
{
    EmoStart.Enabled = false;           //I assume EmoStart is the name of your button
    await Task.Factory.StartNew(Loop);
    EmoStart.Enabled = true;
}

private void Loop()                     //since this method doesn't have async in its signature "var Emo = await FaceEmotion.MakeAnalysisRequest(imageFilePath);" won't compile, so you should change to the synchronous equivalent "var Emo = FaceEmotion.MakeAnalysisRequest(imageFilePath).Result;" --> note that it won't block due to "Task.Factory.StartNew".
{
    string imageFilePath = "C:\\Users\\Administrator\\source\\repos\\FaceDetection\\FaceDetection\\test3.jpg";
    while (...)
    {
        // do your stuff
    }

Then you can decide how you want to cancel the while loop.然后您可以决定如何取消 while 循环。

Option 1 .: you could use a global, bool variable:选项 1 .:您可以使用全局 bool 变量:

private bool emotionsShouldBeProcessed;

and you set it true in EmoStart_Click_1 and false like this:然后在EmoStart_Click_1中将其设置为 true 并设置为 false ,如下所示:

private async void VoiceStart_Click_2(object sender, EventArgs e)
{
    VoiceStart.Enabled = false;
    emotionsShouldBeProcessed = false;
    // start and await voice stuff 
    VoiceStart.Enabled = true;
}

Option 2 .: you could use a CancellationToken to track if cancel is necessary.选项 2 .:您可以使用 CancellationToken 来跟踪是否需要取消。

CancellationTokenSource cSource;

private async void EmoStart_Click_1(object sender, EventArgs e)
{
    EmoStart.Enabled = false;
    cSource = new CancellationTokenSource();
    await Task.Factory.StartNew(() => Loop(cSource.Token));
    EmoStart.Enabled = true;
}
private void Loop(CancellationToken cToken)
{
    string imageFilePath = "C:\\Users\\Administrator\\source\\repos\\FaceDetection\\FaceDetection\\test3.jpg";
    while (true)
    {
        if (cToken.IsCancellationRequested)
            break;
        // otherwise do your stuff
    }
    // some clean up here if necessary
}
private async void VoiceStart_Click_2(object sender, EventArgs e)
{
    VoiceStart.Enabled = false;
    cSource.Cancel();
    VoiceStart.Enabled = true;
}

So far so good!到现在为止还挺好! But your code will crash但是你的代码会崩溃

It will crash whenever you want to set EmoBox.Text as this can happen only on the UI thread.每当您想设置EmoBox.Text时它都会崩溃,因为这只会发生在 UI 线程上。 To avoid this, you need to ask the UI thread to interrupt until Textbox/Label/etc operations are going on, like this:为避免这种情况,您需要请求 UI 线程中断,直到 Textbox/Label/etc 操作正在进行,如下所示:

this.Invoke((MethodInvoket)delegate
{
    EmoBox.Text = "...";
});

Edit:编辑:

I would also check the Emo array whether it is empty since face- and emotion recognitions not always succeeds!我还会检查 Emo 数组是否为空,因为面部和情绪识别并不总是成功! Thus, Emo[0] can result in "Index was out of range" exception.因此,Emo[0] 可能会导致“索引超出范围”异常。 Following code makes sure it isn't empty:以下代码确保它不为空:

var Emo = ...;
if (Emo.Length > 0)
{
    if (...)
        // use Emo[0]
    else if (...)
        // use Emo[0] differently
}

Let me know if there is anything unclear.让我知道是否有任何不清楚的地方。

You can create a bool variable and make the loop while your variable is true.您可以创建一个 bool 变量并在您的变量为真时进行循环。

So set the variable to true, when button1 is clicked.因此,当单击 button1 时,将变量设置为 true。

Then your while would look like this:然后你的 while 看起来像这样:

while(myBoolVariable)

And when button2 is clicked you can change the value to false and the while will stop.当单击 button2 时,您可以将值更改为 false,while 将停止。

You can use a global variable(bool is a good choice)您可以使用全局变量(bool 是一个不错的选择)

when VoiceStart_Click_2 change the variable当 VoiceStart_Click_2 改变变量时

and do check the variable when EmoStart_Click_1 is clicked并在单击 EmoStart_Click_1 时检查变量

if (variable==true)
{
    var Emo = await FaceEmotion.MakeAnalysisRequest(imageFilePath);
    if (Emo[0].FaceAttributes.Emotion.Anger >= 0.5)
    {
       EmoBox.Text = "Anger, Bad Driving Condition, Soft Music will be played";
    }
    ...

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM