Patrick Skelton Ответов: 1

Как начать фоновую работу с обработчика событий?


Очевидно, что в интернете есть тонны всякой всячины .В сети растет число способов многопоточного кода. И это проблема - разработка не только того, какой из них использовать, но и того, как избежать ненужного (и, возможно, опасного) смешивания подходов.

Мои требования кажутся достаточно простыми:
1. я хочу запустить фоновую задачу (повторное подключение Bluetooth) из обработчика событий.
2. Я хочу, чтобы обработчик событий, чтобы быстро заканчиваться.
3. я хочу иметь возможность запустить некоторый код, когда фоновая работа завершится.
4. я хочу поймать любые исключения.
5. Я хочу, чтобы избежать ночных кошмаров, вызванных многочисленными предупреждениями, чтобы избежать async void.

Я был бы благодарен за совет о том, чтобы удовлетворить эти требования с помощью читаемого и безопасного кода.

Что я уже пробовал:

То, что я подозреваю,-это смесь-n-match hotchpotch из доступных вариантов.

Также в попытке использовать BackgroundWorker предложенный @OriginalGriff, теперь у меня есть что-то похожее на это:

// Event handler for when Bluetooth connection is lost.
void BLEAdapter_DeviceConnectionLost( object sender, DeviceErrorEventArgs e )
{
	_reconnectBLEWorker = new BackgroundWorker();
	_reconnectBLEWorker.DoWork += ReconnectBLEWorker_DoWork;
	_reconnectBLEWorker.RunWorkerCompleted += ReconnectBLEWorker_RunWorkerCompleted;
	_reconnectBLEWorker.RunWorkerAsync();
}

// BackgroundWorker work.
async void ReconnectBLEWorker_DoWork( object sender, DoWorkEventArgs e )
{
	int retryCount = 0;
	while( !_bluetoothConnected && retryCount < 10 )
	{
		await KnownDeviceReconnection();
		++retryCount;
	}
	// Act accordingly here, depending on whether Bluetooth connected okay.
}

// Wrap async code so exceptions can be caught and these don't go up into the calling async void event handler.
async Task KnownDeviceReconnection()
{
	try
	{
		IDevice device = await App.BLE.Adapter.ConnectToKnownDeviceAsync( _lastConnectedDeviceGuid );
	}
	catch( Exception ex )
	{
		// Log error.
	}
}

// Event handler for when BackgroundWorker finishes.
void ReconnectBLEWorker_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e )
{
	// This happens immediately.
}


Это не работает. Ясно, что я не понимаю, как это сделать async/await работает, потому что я просто не понимаю, почему в приведенном выше коде BackgroundWorker рабочая нить тут же заканчивается.

BillWoodruff

- То, что я подозреваю,-это смесь-n-match hotchpotch из доступных вариантов."

Голосовали за честность :)

1 Ответов

Рейтинг:
12

OriginalGriff

Использовать BackgroundWorker - он может доложить, чтобы поток пользовательского интерфейса, как надо:

private void FrmMain_Shown(object sender, EventArgs e)
    {
    BackgroundWorker work = new BackgroundWorker();
    work.WorkerReportsProgress = true;
    work.DoWork += Work_DoWork;
    work.ProgressChanged += Work_ProgressChanged;
    work.RunWorkerCompleted += Work_RunWorkerCompleted;
    work.RunWorkerAsync();
    }

private void Work_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
    // Do whatever is necessary after worker complete
    }

private void Work_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
    // Do display updates as connection happens, or gives results.
    }

private void Work_DoWork(object sender, DoWorkEventArgs e)
    {
    // Do the actual connection and subsequent processing here.
    }


johannesnestler

старое, но самое простое решение для этого в .NET UI - 5ed

Patrick Skelton

ООО... Я забыл, что читал об этом много лун назад. Мне это нравится. (Единственное, с чем борется мое ОКР,-это тот факт, что это первые методы FnAsync (), с которыми я столкнулся, которые не ожидаемы, но я думаю, что это приведет меня к полному кругу.) Спасибо!

OriginalGriff

Всегда пожалуйста!

Patrick Skelton

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

OriginalGriff

И как, по-твоему, мы должны это сделать, учитывая, что я не вижу твоего экрана? :смеяться:

Patrick Skelton

Дох! Извините, я забыл упомянуть, что добавил к части вопроса "Что я пробовал" свой последний код. Я сделал это там, чтобы получить правильное форматирование.