Все, у меня есть некоторый сложный код 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();
B. Из события Bgw_DoWork
я запускаю свой метод SQL, который находится в классе HeavyWork
.
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();
}
}
Итак, я хочу запустить дорогой SQL-запрос на отдельном BackgroundWorker
. В методе, вызываемом в потоке BackgroundWorker
(какой-то запрос, отправленный с использованием соединения SQL, назовите его SqlConnection conn
), запустите другой Thread
, который переходит в другой метод, используя отдельный SqlConnection connNew
, который извлекает информацию о главном процессе на conn
.
Я хотел бы знать, это правильный способ сделать это? Кроме того, если возможно запустить новые Thread
s из BackGroundWorker
, так как код выше не запускает метод myMethod
в новом потоке?
Спасибо всем заранее.