从 SQL Server 返回进程信息

本文关键字:进程 信息 返回 Server SQL | 更新日期: 2023-09-27 18:10:48

全部,我有一些复杂的C#代码(Windows Forms(,这些代码大量嵌入了对SQL Server的调用(假定的服务器版本为2008 R2或更高版本(。就目前而言。代码是串行的,我被要求多线程它。这种多线程过程现在专门与代码的昂贵部分相关联,即代码执行"繁重工作"的地方。大部分工作都是使用 SQL Server 查询完成的。

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

A. 从主窗体上的按钮单击事件启动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();  

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

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

C. 从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进入另一个mathod,该重新修订有关conn上主要进程的信息。

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

提前谢谢大家。

从 SQL Server 返回进程信息

如果我理解正确,您想指示进度,但不能,因为ExecNonQuery块。

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

回到您的进度

报告:您的数据库调用块,因此您可以显示的唯一进度是正在运行或已完成,因此我会显示某种选框进度指示器。我会使用 Timer 从 UI 线程控制它 - 你真的不想仅仅为了做动画而启动线程,无论如何你都想在 UI 线程上。

如果你想从后台线程中剥离一个新的线程,那很好。 但是,正如您所说,设置方式在其当前状态下不起作用。

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

。应该变成...

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

。或者简单地...

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