В моем приложении WPF мне нужно запустить быстрый запуск при запуске, который проверяет наличие новой доступной версии. Если версия доступна, мы делаем обновление, а затем хотим немедленно перезапустить приложение. Поскольку это выполняется до появления главного окна пользователю, оно просто выглядит так, как если бы приложение заняло секундную паузу для запуска.Перезапустить приложение WPF из потока, отличного от UI
Мы используем Squirrel.Windows для нашего обновления. Я сделал класс ниже, чтобы обрабатывать проверку/применение обновлений.
public class UpdateVersion
{
private readonly UpdateManager _updateManager;
public Action<int> Progress;
public event Action Restart;
public UpdateVersion(string squirrelUrl)
{
_updateManager = new UpdateManager(squirrelUrl);
}
public async Task UpdateVersions()
{
using (_updateManager)
{
UpdateInfo updateInfo = await _updateManager.CheckForUpdate(progress:Progress);
if (updateInfo.CurrentlyInstalledVersion == null)
{
if (updateInfo.FutureReleaseEntry != null)
{
await _updateManager.UpdateApp(Progress);
// Job crashes here
Restart?.Invoke();
}
}
else if (updateInfo.CurrentlyInstalledVersion.Version < updateInfo.FutureReleaseEntry.Version)
{
await _updateManager.UpdateApp(Progress);
// Job crashes here
Restart?.Invoke();
}
}
}
}
К сожалению Белка сделал свой процесс обновления async
только, что означает, что CheckForUpdate
и UpdateApp
метод должен использовать await
, что делает весь метод обновления асинхронно. Я назначаю вызов asnyc для Task
, а затем просто .Wait()
для завершения обновления.
Проблема возникает, когда я пытаюсь перезагрузить приложение. Основываясь на том, что я прочитал, мне нужно использовать Dispatcher.Invoke
, чтобы вызвать перезапуск из-за того, что при выполнении обновления я нахожусь в потоке, отличном от UI. Тем не менее, несмотря на код ниже, я все еще получаю такое же сообщение об ошибке:
Вызывающий поток не может получить доступ к этому объекту, потому что другой поток владеет
Любая идея, как правильно реализовать Dispatcher.Invoke
для того, чтобы перезапустить приложение?
// Instantiate new UpdateVersion object passing in the URL
UpdateVersion updateVersion = new UpdateVersion(System.Configuration.ConfigurationManager.AppSettings.Get("SquirrelDirectory"));
// Assign Dispatch.Invoke as Restart action delegate
updateVersion.Restart +=() =>
{
Dispatcher.Invoke(() =>
{
Process.Start(ResourceAssembly.Location);
Current.Shutdown();
});
};
// This is here for debugging purposes so I know the update is occurring
updateVersion.Progress += (count) =>
{
Debug.WriteLine($"Progress.. {count}");
};
var task = Task.Run(async() => { await updateVersion.UpdateVersions(); });
task.Wait();
EDIT
Ниже приведен снимок экрана атрибута Restart
действия Target
. Отладчик был приостановлен на линии Restar?.Invoke
сверху.
Где работает код, это в вашей программе. cs или событие 'Application'? – CodingGorilla
Нет файла Program.cs, это метод «OnStartup» приложения. Это первая команда, выполняемая программой. – NealR
Вы можете подумать о добавлении 'Program.cs' с помощью метода' Main' (например, консольного приложения), установите это как ваш объект запуска (в разделе «Свойства -> Приложение»), а затем выполните обновление. Таким образом, вы можете просто не запускать основное окно, когда есть обновление, которое нужно выполнить. – CodingGorilla