从SQL Server返回进程信息

时间:2011-10-10 14:48:20

标签: c# sql multithreading

所有,我有一些复杂的C#代码(Windows窗体),它们大量嵌入了对SQL Server的调用(2008 R2或更高版本是假定的服务器版本)。就目前而言。代码是串行的,我被要求多线程。这种多线程处理现在特别与代码的昂贵部分相关联,即代码执行“重提升”的部分。大部分工作都是通过SQL Server查询完成的。

我即将开始处理多线程处理SQL Server调用的主处理器。我希望通过“SQL线程”的进度向用户提供信息,因为SQL过程可能很长。我想知道我的方法听起来是否合理,或者是否有更好的方法。我的方法如下:(注意:下面的代码只是我在尝试使用实际代码之前构建的一个小例子)

一个。从主窗体上的按钮单击事件开始BackgroundWorker线程。

Bgw = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true };
Bgw.DoWork += new DoWorkEventHandler(Bgw_DoWork);
Bgw.ProgressChanged += new ProgressChangedEventHandler(Bgw_ProgressChanged);
Bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Bgw_RunWorkerCompleted);
Bgw.RunWorkerAsync();  

B中。从Bgw_DoWork事件中,我启动了位于类HeavyWork中的SQL方法。

void Bgw_DoWorkSQL(object sender, DoWorkEventArgs e)
{
    Hw = new HeavyWork(this, ref Bgw, ref e);
    Hw.SQLProc();
    return;
} 

℃。从BackgroundWorker开始,从BackgroundWorker启动另一个后台线程(此时 Hw.SQLProc),以便捕获SQL查询的进度并促进取消SQL Server查询。

// Globals.
private bool bConnOpen = false;
private SqlConnection conn = null;
private Form _MainForm; 
private BackgroundWorker _Bgw;
private DoWorkEventArgs _e;    

public void SQLProc()
{
    bool bConnOpen = false;
    const string strSqlConnMaster = "Data Source = localhost; Initial Catalog = RMH1006DHFinal; Integrated Security " + "= True; MultipleActiveResultSets = True; Connection Timeout = 0";

    const string strSQL = "DBCC CHECKDB"; // Expensive SQL Non-Query.

    try
    {
        // Create new SQL connection.
        conn = new SqlConnection(strSqlConnMaster);

        // Execute the SQL Non-Query.
        conn.Open();
        bConnOpen = true;

        // Start another thread to get user information and for cancellation purposes.
        Thread SQLThread = new Thread(myMethod); // This is not working.
        SQLThread.IsBackground = true;
        SQLThread.Start();           

        // Now run big query.
        _Bgw.ReportProgress(0, String.Format("Processing SQL Command '{0}'...", strSQL));
        ExecNonQuery(conn, strSQL);
        conn.Close();
        bConnOpen = false;

        return;
    }
    catch (Exception)
    {
        throw;
    }
    finally
    {
        if (bConnOpen)
            conn.Close();
    }
}

总之,我想在单独的BackgroundWorker上启动昂贵的SQL查询。在BackgroundWorker线程调用的方法中(使用SQL连接发送的某些查询,称之为SqlConnection conn),启动另一个Thread,使用单独的SqlConnection connNew进入另一个方法它会在conn上撤消有关主要流程的信息。

我想知道这是一种有效的方法吗?另外,如果可以从Thread启动新的BackGroundWorker,因为上面的代码没有在新线程上启动myMethod方法?

提前谢谢大家。

2 个答案:

答案 0 :(得分:1)

如果你想从你的后台线程中分离一个新线程,那很好。但是,正如您所说,如何设置它将无法在其当前状态下工作。

Thread SQLThread = new Thread(myMethod); // This is not working. 

......应该成为......

Thread SQLThread = new Thread(new ThreadStart(myMethod));
...

......或者只是......

Thread SQLThread = new Thread(()=>myMethod());

答案 1 :(得分:1)

如果我理解正确,你想表明进展,但不能因为ExecNonQuery阻止。

作为一个好的做法,如果您的数据库调用可能需要超过一秒钟,我将不会使用BackgroundWorker,因为BW使用线程池线程。相反,我会使用一个新的线程,或者,如果你在.NET 4.0上,使用TaskCreationOptions.LongRunning的任务。

返回进度报告:您的数据库调用阻止,因此您可以显示的唯一进度正在运行或已完成,因此我将显示某种选取框进度指示器。我会使用一个Timer从UI线程控制它 - 你真的不想只是为了做一个动画来启动一个线程而你想要在UI线程上。