как получить уведомление о завершении задачи в ветке без графического интерфейса - PullRequest
0 голосов
/ 25 июля 2011

Справочная информация: я использовал для вызова хранимой процедуры во время загрузки формы. Однако, поскольку это привело к неоптимальному взаимодействию с пользовательским интерфейсом, я поместил свой вызов SP в отдельную задачу внутри события Shown. Поскольку это, как правило, последнее событие в процессе отображения формы, оно дает гораздо лучший результат, чем вставка содержимого в событие загрузки формы. У меня есть:

private void MainForm_Shown(object sender, EventArgs e)
{
   dbCheckTask = Task<bool>.Factory.StartNew(RunSPAndCheckStuff());

  // both of below run on the GUI thread.

  // if I print the thread ID in mycallback it is the GUI thread id
  dbCheckTask.ContinueWith(mycallback());  

  // I also tried below. But obviously, that too runs on the GUI thread
  mycallback(dbCheckTask.Result)

}

Поскольку они запускаются в потоке графического интерфейса, моя краска при запуске формы все еще не является ни мгновенной, ни гладкой. Как я могу завершить обратный вызов моей задачи в потоке без графического интерфейса, не прибегая к событиям? Всякий раз, когда задача завершается и если что-то не так, и только если что-то не так (результат bool вернул false), пользователь получает всплывающее окно с сообщением. До тех пор он мог делать другие вещи, не связанные с базой данных, в форме. Посоветуйте, пожалуйста, как я могу получить ответный вызов завершения задачи с результатом задачи в потоке без графического интерфейса пользователя. Спасибо

Ответы [ 4 ]

3 голосов
/ 25 июля 2011

Все эти материалы лучше всего адресованы расширениям языка Async, которые можно загрузить здесь , и имеют домашнюю страницу здесь .

В нем представлены async и await ключевых слов для C # и VB, которые позволят вам писать код, который без усилий переключается между пользовательским интерфейсом и фоновыми потоками даже в рамках одного метода.Компилятор преобразует это в задачи, продолжения, перехват ошибок и т. Д. Без каких-либо проблем.Вот пример, который вас заинтересует:

    public async void AsyncSwitchToCPU()    {
    Console.WriteLine("On the UI thread.");

    // Switch to a thread pool thread:
    await new SynchronizationContext().SwitchTo();  

    Console.WriteLine("Starting CPU-intensive work on background thread...");
    int result = DoCpuIntensiveWork();
    Console.WriteLine("Done with CPU-intensive work!");

    // Switch back to UI thread
    await Application.Current.Dispatcher.SwitchTo();                

    Console.WriteLine("Back on the UI thread.  Result is {0}.", result);
}

public int DoCpuIntensiveWork()
{
    // Simulate some CPU-bound work on the background thread:
    Thread.Sleep(5000);
    return 123;
}

У него даже есть действующая лицензия (с некоторыми оговорками от MS).Очень элегантный материал, заимствованный из F #.

Ргдс Герт-Ян

1 голос
/ 25 июля 2011

Я бы использовал BackgroundWorker для этого лично.Один из способов заставить ваш обратный вызов работать в потоке задач - изменить вызов метода и создание задачи следующим образом:

private void MainForm_Shown(object sender, EventArgs e)
{
    dbCheckTask = Task<bool>.Factory.StartNew(() => RunSPAndCheckStuff(mycallback));
    ...
}

private bool RunSPAndCheckStuff(Action<bool> callback)
{
    bool result = false;
    // Do stuff
    callback(result);
    return result;
}
1 голос
/ 25 июля 2011

Вы должны изучить использование асинхронных API, а не вызывать синхронные версии в фоновом потоке:

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.beginexecutenonquery.aspx

Преимущество в том, что ни один поток не будет заблокирован, и я считаю, что обратный вызов будет вызван в потоке ThreadPool, например, НЕ в потоке GUI. Оттуда вы можете маршалировать любые вызовы GUI обратно в поток GUI с помощью Invoke / BeginInvoke.

0 голосов
/ 25 июля 2011

Почему бы не сделать:

Task.Factory.StartNew(()=>WorkerMethod());

И определить WorkerMethod () как:

void WorkerMethod()
{
     RunSPAndCheckStuff(); // this blocks until finished
     DoSomeMoreStuff(); // then this continuous
}

В противном случае предоставьте более подробную информацию о том, чего вы хотите достичь.

...