C#在单独的线程中连接到数据库

C#在单独的线程中连接到数据库,c#,sql-server,database,multithreading,C#,Sql Server,Database,Multithreading,我有一个应用程序,它位于任务栏中,定期检查数据库(通过SQLConnection)。如果数据库无法访问,它只会在notify图标上显示红色状态,而不会显示其他状态。这是因为用户将使用笔记本电脑在设施之间移动,并且只有在内部网络上或通过VPN连接时才能访问数据库 我遇到的问题是,当数据库无法访问时,我仍然希望notify图标上下文菜单能够响应。当前,如果用户在数据库尝试连接时尝试与菜单交互,则线程将被连接尝试锁定 我希望数据库连接发生在一个单独的线程中,但我知道在线程之间共享连接对象是一件不好的事

我有一个应用程序,它位于任务栏中,定期检查数据库(通过SQLConnection)。如果数据库无法访问,它只会在notify图标上显示红色状态,而不会显示其他状态。这是因为用户将使用笔记本电脑在设施之间移动,并且只有在内部网络上或通过VPN连接时才能访问数据库

我遇到的问题是,当数据库无法访问时,我仍然希望notify图标上下文菜单能够响应。当前,如果用户在数据库尝试连接时尝试与菜单交互,则线程将被连接尝试锁定

我希望数据库连接发生在一个单独的线程中,但我知道在线程之间共享连接对象是一件不好的事情。数据库连接后,我需要从原始线程查询它。有什么好办法吗

我知道我可以在一个新线程中使用一个函数,简单地检查连接是否失败,然后如果返回成功,原始线程可以继续运行并连接它自己的数据库对象。但这种方法似乎是个糟糕的变通方法。想法

谢谢


谢谢你的建议,我从他们身上学到了很多。最后,我做了我从一开始就应该做的事情。只要需要定期更新数据库,主(UI)线程就会启动一个新线程(包括数据库对象创建和连接)

因此,正如HenkHolterman在对我的原始消息的评论中所建议的那样,我真的不需要创建数据库并在单独的线程中使用它运行操作

一旦升级到VS2010,我肯定会对使用SqlConnection.OpenAsync感兴趣


再次感谢。

使用对象应该以一种简单的方式解决您的问题,但更准确地说,您可能希望使用线程来尝试打开连接,让UI线程随时准备接收用户输入。

我建议使用新的线程,这样可以让您留在UI线程上,从而降低复杂性


A
SqlConnection
没有线程关联要求,因此您可以在单独的线程上创建和打开它,并将引用传递回UI线程。只要不从多个线程同时调用同一实例上的任何属性或方法,就不会有任何问题

使用
Task
类(System.Threading.Task)在后台启动此操作,然后调用
ContinueWith
将实例的所有权转移回UI线程

public class TrayIconForm : Form
{
  private SqlConnection connection = null;

  private void Form_Load(object sender, EventArgs args)
  {
    TaskScheduler ui = TaskScheduler.FromCurrentSynchronizationContext();

    Task.Factory.StartNew(() =>
      {
        var sql = new SqlConnection();
        sql.ConnectionString = "your connection string";
        sql.Open();
        return sql;
      }).ContinueWith((task =>
      {
        connection = task.Result;
        // You can access other UI elements here as needed.
      }), ui);
  }
}
有了新的
async
wait
关键字,将在C#5.0中引入,现在可以通过async CTP实现这一点

private async void Form_Load(object sender, EventArgs args)
{
  connection = await Task.Run(() =>   // TaskEx.Run in the CTP
    {
      var sql = new SqlConnection();
      sql.ConnectionString = "your connection string";
      sql.Open();
      return sql;
    });
}

有点冒险?当.Open()阻塞数秒时,这不是一个真正的选项。看起来是一个很好的解决方案,但我还没有决定完成公司订购升级到VS2010的艰巨过程-仍然是VS2008。谢谢你的建议@亨克霍特曼我想你已经试过了。“我在F#中对这个编程模型有很好的经验,并且强烈建议在C#中使用它。@HenkHolterman异步编程的精神是要求执行一个长时间运行的操作,并提供一个回调,比如Brian Gideon代码中的ContinueWith。不同之处在于将与应用程序相关的所有内容保持在同一线程上,这样就不会因为线程/同步而出现故障。即使在.NET1.1中也可以使用,这种冒险性如何?我错过了什么?为什么需要在原始线程中查询?它可能会再次阻塞。一旦后台线程打开连接,我如何从UI线程与它交互?我是否需要在UI线程中创建连接对象,将其传递给连接线程,并在连接线程完成后继续?这完全取决于您需要对该连接执行什么操作。注意螺纹安全。如果您使用的对象在两个线程之间的作用域中共享,请在使用时小心锁定该对象。您只需将打开的连接传递给已完成的事件。