所有,我有一些复杂的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
方法?
提前谢谢大家。
答案 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线程上。