Прямо сейчас у меня есть функция, которая выполняет запрос, используя ADO и возвращает recordset:ADO: Как выполнить запрос синхронно с возможностью отмены?
Recordset Execute(Connection connection, String commandText)
{
//[pseudo-code]
Recordset rs = new Recordset();
rs.CursorLocation = adUseClient;
rs.CursorType = adOpenForwardOnly;
rs.Open(commandText, connection,
adOpenForwardOnly, //CursorType; the default
adLockReadOnly, //LockType
adCmdText);
return rs;
}
И это прекрасно. Он работает синхронно и возвращает набор записей запроса.
Теперь я хочу такой же вариант, что показывает ProgressDialog, предоставляя пользователю возможность отменить давний запрос:
Recordset Execute(HWND parenthWnd, String caption, Connection connection, String commandText)
{
//[pseudo-code]
//Construct a progressDialog and show it
IProgressDialog pd = new ProgressDialog();
pd.SetTitle(caption); //e.g. "Annual Funding Report"
pd.SetCancelMsg("Please wait while the operation is cancelled");
pd.StartProgressDialog(parenthWnd, null, PROGDLG_MODAL | PROGDLG_NOTIME | PROGDLG_NOMINIMIZE, null);
pd.SetLine(1, "Querying server", False, null);
try
{
//Query the server
Recordset rs = new Recordset();
rs.Open(commandText, connection,
adOpenForwardOnly, //CursorType
adLockReadOnly, //LockType
adCmdText | adAsyncExecute);
while (rs.State and (adStateConnecting+adStateExecuting+adStateFetching) <> 0)
{
if pd.HasUserCancelled()
throw new EUserCancelledOperationException();
Sleep(100);
};
finally
{
//Hide and destroy the progress dialog
pd.StopProgressDialog();
pd = null;
}
//Now we have our results for the client
return rs;
}
Для проверки того, если пользователь отменил операция периодически спрашивают диалог выполнения, если пользователь, как нажал кнопку отмены:
pd.HasUserCancelled(); //returns true if user has clicked Cancel
Теперь я сталкиваюсь с тем, как периодически проверять, если пользователь отменил (d знать, завершен ли запрос или произошла ошибка), и быть хорошим программистом и делать это без опроса.
Единственный способ узнать, что случилась ошибка, чтобы иметь обработчик на FetchCompleteEvent набора записей:
pError
Объект Error. Он описывает ошибку, которая произошла, если значение adStatus - adStatusErrorsOccurred; иначе он не будет установлен.
adStatus
Значение статуса EventStatusEnum. Когда это событие вызывается, этот параметр устанавливается в adStatusOK, если операция, вызвавшая событие, была успешной, или adStatusErrorsOccurred, если операция завершилась неудачно.Прежде чем это событие вернется, установите этот параметр в adStatusUnwantedEvent, чтобы предотвратить последующие уведомления.
pRecordset
Объект Recordset. Объект, для которого были получены записи.
Так что это означало бы, что мне нужно будет построить мою функцию вспомогательного объекта, поэтому у меня может быть обработчик FetchComplete
. Но тогда я должен предотвратить немедленное возвращение функции синхронной функции. И затем мы попадаем в MsgWaitForSingleObject
, что, как известно, сложно использовать правильно.
Так что я прошу помощи или законсервированного кода.
я должен быть более четко: я ищу для реализации функции с помощью этого метода подписи:
Recordset ExecuteWithCancelOption(Connection connection, String commandText)
, который показывает диалоговое окно с помощью кнопки отмены на нем.
Задача состоит в том, что функция должна теперь создавать все, что требуется для достижения этого. Если это связано с скрытой формой, на которой есть таймер, и т. Д. - хорошо.
Но я ищу для синхронного функции, которая отображает Отмену кнопку.
И функция будет рядом (или точнее) вставных замены для
Recordset Execute(Connection connection, String commandText)
С учетом практических соображений, на Windows, я должен был бы поставить функцию с родительского окна ручкой, что он будет родитель его диалог с:
Recordset ExecuteWithCancelOption(HWND parentHwnd, Connection connection, String commandText)
И учитывая, что это будет многоразовая функция, я дам звонящему предоставить текст, который будет отображаться:
Recordset ExecuteWithCancelOption(HWND parenthWnd, String caption, Connection connection, String commandText)
И учитывая, что эти обе функции класса в моем TADOHelper
классе, я могу дать им такое же имя, и у них будет перегруженные друг друга:
Recordset Execute(HWND parenthWnd, String caption, Connection connection, String commandText)
Я думаю, в других чем Delphi языках, анонимные делегаты полезны. Но я все еще боюсь иметь дело с MsgWaitForMultipleObjects
.
Таймер будет таким же, как «Сон». Он не фиксирует реальную проблему при опросе, и я не могу получить доступ к аргументу «Ошибка». –
Таймер - это не то же самое, что Sleep. Сон: приостанавливает выполнение программы за указанное количество микросекунд. Таймер может проверять каждую секунду, чтобы проверить, выполнено ли какое-либо другое условие. – Leslie