【发布时间】:2018-02-08 04:25:47
【问题描述】:
我一直无法让以下 C# 线程代码正常运行。我通过单击表单上的按钮来启动一个线程,该线程简单地声明一个浮点 x 并在循环中递增它,直到 threadRunning 设置为 false。当我再次单击该按钮时,我将 threadRunning 设置为 false。当循环完成时,线程将threadResult 设置为递增值x。然后我在表单上显示threadResult。
问题是threadResult 在这种情况下总是设置为 256.0。如果我选择将x 增加0.0001f,那么threadResult 将始终设置为2048.0。每次线程运行时,这些固定值都会分配给threadResult。除非我在递增的行x += 0.00001f; 上放置了一个断点。这可以是条件设置为 false 的条件断点;只要此行上存在启用的断点,x 就会正确递增并分配给threadResult。
---编辑 1---
为了阐明正确的行为是什么,仅当增量行上存在启用的断点时才会发生:threadResult 被分配的值等于增量行被命中的次数乘以增量值。因此,如果x 增加了 121 次,并且增量值为 0.00001f,则threadResult 应该变为 0.00121。当增量行上存在启用的断点并且我在调试模式下运行时,确实会发生。
另外,当我在发布模式下运行它时,当我单击按钮停止线程时程序会挂起,所以我假设我的线程实现完全有问题。我仍然会感谢任何关于我的代码可能存在问题的指针。我只是想写一些东西来测试停止线程。此外,我不想使用 BackgroundWorkers,因为我的线程代码不打算与 Windows 窗体一起使用。 ---结束编辑1---
谁能向我解释这里发生了什么?通过在线程外部将线程的循环控制变量设置为 false,我用来停止线程的方法是否可以?我在 Visual Studio 2017、2015 和 2013 中尝试过这段代码,结果都一样。
这里是代码。该表单仅包含一个名为 button1 的按钮和一个名为 textBox1 的文本框。
using System;
using System.Windows.Forms;
using System.Threading;
namespace ThreadingTesting
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
button1.Click += Button1_Click;
}
private Thread thread;
private bool threadRunning = false;
private float threadResult = 0;
private void Button1_Click(object sender, EventArgs e)
{
if (threadRunning)
{
threadRunning = false;
thread.Join();
textBox1.Text = "Result: " + threadResult.ToString("N4");
button1.Text = "Start Thread";
}
else
{
thread = new Thread(new ThreadStart(ThreadedWork));
thread.Start();
textBox1.Text = "Thread Started!";
button1.Text = "Stop Thread";
}
}
private void ThreadedWork()
{
threadRunning = true;
float x = 0.0f;
while (threadRunning)
{
x += 0.00001f;
}
threadResult = x;
return;
}
}
}
【问题讨论】:
-
尝试查找关键字
volatile。 -
thread only runs properly when breakpoint exists您看到的不当行为是什么?您正在寻求的正确行为是什么? -
如果您试图不阻止用户界面,您应该查看
async/await -
这里的线程代码和数学代码都不正确。线程逻辑和浮点运算都很棘手,需要相当多的知识才能正确。不要使变量易变; 了解为什么如果您必须使变量 volatile 来解决线程问题,那么您可能使用了错误的工具来解决问题。
标签: c# .net multithreading winforms visual-studio