2013-04-11 4 views
2

Short VersionАргумент доступа передан в BackgroundWorker, даже если существует Исключение?

Как получить доступ к аргумент, передаваемый в BackgroundWorker в RunWorkerCompleted случае, если есть исключения, сгенерированные?

Longer Версия

Я использую BackgroundWorker компонент в моем приложении. При запуске приложения я запрашиваю базу данных, чтобы получить список нежелательных сообщений. Затем, используя GSM-модем (внутри рабочего стола), я отправляю сообщения один за другим.

Теперь, как только я решил отправить сообщение, я добавляю его в список под названием В настоящее время HandledMessages. Это гарантирует, что 2 модема не отправят одно и то же сообщение.

Теперь я перехожу идентификатор сообщения в BackgroundWorker в качестве аргумента, и он посылает сообщение, и RunWorkerCompleted события происходит, и я удалить идентификатор из CurrentlyHandledMessages списка. Я передаю результат как кортеж.

e.Result = new Tuple<int, String>(idToHandle, response); 

Это прекрасно работает, если не было никаких исключений.

Однако я не могу понять, как я могу получить аргумент, переданный BackgroundWorker, если возникло исключение. Потому что в событии RunWorkerCompleted я хочу удалить id независимо от того, что.

ответ

2

Существует нет встроенного способа получения аргумента, который был передан (в этом случае идентификатор). Вам нужно будет передать его самостоятельно. Я бы рекомендовал просто передать ему все время, независимо от исключения, так что представьте, что-то вроде этого внутрь DoWork обработчика:

string response; 

try 
{ 
    ... 

    response = "something"; 
} 
catch (Exception ex) 
{ 
    response = e.ToString(); 
} 
finally 
{ 
    e.Result = new Tuple<int, string>((int)e.Argument, response); 
} 

и теперь, независимо от результата, который вы собираетесь получить, что ID в обработчик RunWorkerCompleted.

+0

Если я поймаю исключение и не переброшу его, будет ли он по-прежнему доступен в 'e.Error' в событии RunWorkerCompleted? –

+0

@ RanhiruCooray, хороший вопрос, и я не знаю, но это тоже безопасно. Оставь все остальное тем же и заново, потому что это все равно ударит наконец. –

1
private void bgw_DoWork(object sender, DoWorkEventArgs e) 
{ 
    try 
    { 
     // do the work 
    } 
    catch (Exception ex) // on error 
    { 
     e.Error = ex; 
     e.Result = "set the data here"; 
    } 
} 

на полном событии

Проверка на e.Error первый, затем e.Cancelled и, наконец, e.Result

1

Вы можете передать информацию через Error свойство RunWorkerCompletedEventArgs.

Вам нужно обрабатывать исключение и бросать пользовательских исключений с Id и Response

0

Согласно MSDN

Ваш обработчик события RunWorkerCompleted всегда должны проверить AsyncCompletedEventArgs.Error и AsyncCompletedEventArgs.Cancelled свойства перед доступом свойство RunWorkerCompletedEventArgs.Result . Если было создано исключение или операция была отменена, , обращаясь к RunWorkerCompletedEventArgs.Свойство Result вызывает исключение .

0

Просто проистекают из BackgroundWorker и осуществить требуемое свойство:

public class CustomBackgroundWorker : BackgroundWorker 
{ 
    public object Argument { get; private set; } 

    protected override void OnDoWork(DoWorkEventArgs e) 
    { 
     Argument = e.Argument; 
     base.OnDoWork(e); 
    } 
} 

Затем к нему доступ из RunWorkerCopmleted и других событий следующим образом:

private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    object originalArgument = ((CustomBackgroundWorker)sender).Argument; 

    // The rest of the stuff 
    if (e.Cancelled) { ... } 
    if (e.Error) {...} 
    ... 
} 

Регулируя семантику ошибка остается неповрежденным