这是我第一次尝试在应用程序中使用线程。虽然我知道这个问题以前已经被问过了,但是在我查看的解决方案中,我无法看出如何将它们应用到我的情况中。
我有一个程序,其中一个datagridview每60秒刷新一次。数据来自SQL数据库。这个计时器也会启动一个工作线程,在后台查找特定的蓝牙设备并根据其结果更新数据库。由于蓝牙查找特别慢,因此我将其放在了工作线程中。
我的问题是,有时新的工作线程会在之前的线程完成之前启动。至少这是我得到的错误的唯一合理解释。最明显的提示是文件锁定错误,当唯一可能锁定文件的是同一应用程序的另一个工作线程时。
以下是我用来启动后台线程的代码。
private void timerScreenRefresh_Tick(object sender, EventArgs e)
{
if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", "");
// If the user is not on a Remote desktop connection
if (!remoteDesktopUser)
{
// Run the Bluetooth Search in a worker thread
Thread thread = new Thread(new ThreadStart(this.checkProximity));
thread.IsBackground = true;
thread.Start();
}
// Load User Data from the DB and display on the screen
loadUserData();
}
似乎解决方案是使用thread.IsAlive(),但我找不到一个好的例子。在刚刚用"Thread thread = new Thread()"创建了一个新线程时尝试检查线程的存在似乎很奇怪。
显然,我漏掉了什么。我正在使用Visual Studio 2008。 感谢任何想法 David
更新
基于krw12572提出的解决方案,我尝试了这个...
我将!=改为==,因为我仍然希望每次都在主线程中运行loadUserData()方法。
在编辑器中,我会在"_bluetoothSearchThread"上得到绿色下划线,告诉我该字段从未被分配,并且永远具有NULL值。
在运行时,我在这一行收到了"Object Reference Not Set to An instance of an object"错误。
if (_bluetoothSearchThread == null && _bluetoothSearchThread.IsAlive)
这个值是如何被分配的?
private Thread _bluetoothSearchThread;
private void timerScreenRefresh_Tick(object sender, EventArgs e)
{
if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", "");
// Check if Worker Thread is already running.
if (_bluetoothSearchThread == null && _bluetoothSearchThread.IsAlive)
{
if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", "Previous Worker Thread not running");
// If the user is not on a Remote desktop connection
if (!remoteDesktopUser)
{
// Check if the users mobile phone is within range
// Run the Bluetooth Search in a worker thread
Thread thread = new Thread(new ThreadStart(this.checkProximity));
thread.IsBackground = true;
thread.Start();
}
}
else
{
if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", "Worker Thread still running don't start another one");
}
// Load User Data from the DB and display on the screen
loadUserData();
}
更新2
好的,我想我已经弄清楚了。 我把“!= Null”改回了原样,并把IF和Else的顺序倒过来。
然后我得动一下脑筋,将“thread”改成了“_bluetoothSearchThread”。
现在代码可以编译并运行。现在我只需要通过触发导致文件锁定错误的条件来测试它,看看是否真正解决了原始问题。如果有效,我将标记krw12572的答案为正确答案。
更新2.5 我还不得不移动这一行,以便它不会太早地创建新实例。
_bluetoothSearchThread = new Thread(new ThreadStart(this.checkProximity));
所以这就是可行的解决方案。
private Thread _bluetoothSearchThread;
private void timerScreenRefresh_Tick(object sender, EventArgs e)
{
if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", "");
// Check if Worker Thread is already running.
if (_bluetoothSearchThread != null && _bluetoothSearchThread.IsAlive)
{
// Thread is still running. Just log it and move on.
if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", "******** Worker Thread still running don't start another one *********");
}
else
{
if (LocalUtilities.Debug > 3) LocalUtilities.writeLogFile(4, "Primary", LocalUtilities.getCurrentMethod() + "()", "Previous Worker Thread not running");
// If the user is not on a Remote desktop connection
if (!remoteDesktopUser)
{
// Check if the users mobile phone is within range
// Run the Bluetooth Search in a worker thread
_bluetoothSearchThread = new Thread(new ThreadStart(this.checkProximity));
_bluetoothSearchThread.IsBackground = true;
_bluetoothSearchThread.Start();
}
}
// Load User Data from the DB and display on the screen
loadUserData();
}