2016-11-30 22 views
2

这是我第一次尝试在应用程序中使用线程。 我知道这个问题之前已经问过,但我看过的解决方案我看不到如何将它们应用于我的情况。c#如何检查一个线程是在开始另一个线程之前完成

我有一个程序,每60秒刷新一次定时器上的datagridview。数据来自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的 感谢您的任何想法 大卫

UPDATE通过krw12572下面我试图此基础上提出的解决方案

...

我改变了!=来==,因为我仍然希望每次都在主线程中运行loadUserData()方法。

在编辑器中,我在“_bluetoothSearchThread”上得到一个绿色下划线,告诉我该字段永远不会被分配,并且总是有NULL值。

在运行时,我得到一个“对象引用未设置为对象的实例”错误在这一行上。

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绕过另一个方向。

然后,我不得不用我的大脑有点,改变了“线”到“_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(); 
    } 
+0

在这里你的结果:http://stackoverflow.com/questions/12949024/detecting-a-thread-is-already-running-in-c-sharp-net –

+0

@BALA我以前见过这个解决方案。它似乎过于复杂,我并不真正了解它。我会试着明天盲目跟随它,看看是否有可行的东西出来。 –

+0

可能重复[如何检查线程是否执行完成](http://stackoverflow.com/questions/2773479/how-to-check-if-thread-finished-execution) –

回答

4

如果你想只有一个线程运行的时间,那么你可以创建一个字段来存储线程实例。使用该线程实例,您可以使用_threadInstance.IsAlive来检查它是否已在运行。

private Thread _bluetoothSearchThread; 
private void timerScreenRefresh_Tick(object sender, EventArgs e) 
{ 
    if(_bluetoothSearchThread != null && _bluetoothSearchThread.IsAlive) 
     return;  //It means one thread is already performing the search operation. 

    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 
     _bluetoothSearchThread = new Thread(new ThreadStart(this.checkProximity)); 
     _bluetoothSearchThread.IsBackground = true; 
     _bluetoothSearchThread.Start(); 
    } 

    // Load User Data from the DB and display on the screen 
    loadUserData(); 
} 
+0

我试过了。它有一些问题。我更新了我的问题,以包含您提出的解决方案和错误消息。谢谢大卫 –

+0

我更新了我的答案。而不是创建Thread thread = new Thread(..),为线程实例使用新创建的字段。 _bluetoothSearchThread =新主题(...) –

4

编辑:

研究,在您使用situtation后Thread.IsAlive是不是一种安全的方式来做到这一点。

您应该使用Threa.Join()

文档:

块调用线程,直到这个 实例所表示的线程终止或特定的时间之后,在继续 执行标准的COM和SendMessage消息抽水。

例子:

while(!currentThread.Join(0)) //should specify the time if you dont want it to be blocking. 
{ 
    ///thread is ongoing 
} 
Console.WriteLine("while loop has breaked! so the thread is finished!"); 
+0

我如何在我的示例代码中使用Thread.IsAlive。你能给我一些想法吗? –

+0

@DavidPollard'if(thread.isAlive)//然后做任何事情; ' –

+0

@DavidPollard嗨,我刚刚编辑了aswer –

0

你可能想使用Task而不是Thread

// Create dummy task 
Task task = Task.Run(() => { }); 

private void timerScreenRefresh_Tick(object sender, EventArgs e) 
{ 
    ... 
    // add continuation to current task 
    task.ContinueWith(t => checkProximity); 
    ... 
} 

新任务将只在前一个之后执行。

但是,如果任务在Tick期间没有时间运行,它们将累积在队列中。

+0

嗨亚历山大,我正在考虑任务作为替代,虽然我没有点排队子任务。我现在明白krw12572的建议和我的解决方案现在的工作。为了测试,我将计时器记号设置为10秒,我可以从日志中看到它正在打开和关闭所有地方的线程。上面的代码是非常有序的。线程11开始,直到线程11完成后才开始。所以现在我得到的任何其他错误都与重叠的线程无关。感谢您的想法。大卫 –

相关问题