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

标签 c# sql-server database multithreading

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

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

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

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

谢谢!


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

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

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

再次感谢。

最佳答案

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);
  }
}

使用新的 asyncawait 关键字将在 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;
    });
}

关于C#在单独的线程中连接到数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10213631/

相关文章:

sql-server - SQL Server - 如果不存在则创建临时表

sql-server - 如何在sql server中获取两个日期之间的当前月份名称,开始日期和结束日期

c# - SqlCommand select from where 问题

mysql - sql中的数据库时间戳

mysql - 只允许一个唯一的外键作为主键

c# - 通过单击按钮将值从 form1 传递到 form2

C# Linq 查询帮助删除 foreach 循环创建更清晰的代码

c# - 在 Windows 8 Metro 应用程序中禁用鼠标悬停焦点

php - 保护数据库连接字符串的最佳方法是什么?

c# - TcpListener - 无法建立连接,因为目标机器主动拒绝它