diff --git a/OpenRA.Game/Download.cs b/OpenRA.Game/Download.cs index 43032385d7..9521594def 100644 --- a/OpenRA.Game/Download.cs +++ b/OpenRA.Game/Download.cs @@ -17,8 +17,8 @@ namespace OpenRA { public class Download { + readonly object syncObject = new object(); WebClient wc; - bool cancelled; public static string FormatErrorMessage(Exception e) { @@ -28,6 +28,8 @@ namespace OpenRA switch (ex.Status) { + case WebExceptionStatus.RequestCanceled: + return "Cancelled"; case WebExceptionStatus.NameResolutionFailure: return "DNS lookup failed"; case WebExceptionStatus.Timeout: @@ -41,40 +43,42 @@ namespace OpenRA } } - public Download(string url, string path, Action onProgress, Action onComplete) + public Download(string url, string path, Action onProgress, Action onComplete) { - wc = new WebClient(); - wc.Proxy = null; - - wc.DownloadProgressChanged += (_, a) => onProgress(a); - wc.DownloadFileCompleted += (_, a) => onComplete(a, cancelled); - - Game.OnQuit += Cancel; - wc.DownloadFileCompleted += (_, a) => { Game.OnQuit -= Cancel; }; - - wc.DownloadFileAsync(new Uri(url), path); + lock (syncObject) + { + wc = new WebClient { Proxy = null }; + wc.DownloadProgressChanged += (_, a) => onProgress(a); + wc.DownloadFileCompleted += (_, a) => { DisposeWebClient(); onComplete(a); }; + wc.DownloadFileAsync(new Uri(url), path); + } } - public Download(string url, Action onProgress, Action onComplete) + public Download(string url, Action onProgress, Action onComplete) { - wc = new WebClient(); - wc.Proxy = null; - - wc.DownloadProgressChanged += (_, a) => onProgress(a); - wc.DownloadDataCompleted += (_, a) => onComplete(a, cancelled); - - Game.OnQuit += Cancel; - wc.DownloadDataCompleted += (_, a) => { Game.OnQuit -= Cancel; }; - - wc.DownloadDataAsync(new Uri(url)); + lock (syncObject) + { + wc = new WebClient { Proxy = null }; + wc.DownloadProgressChanged += (_, a) => onProgress(a); + wc.DownloadDataCompleted += (_, a) => { DisposeWebClient(); onComplete(a); }; + wc.DownloadDataAsync(new Uri(url)); + } } - public void Cancel() + void DisposeWebClient() { - Game.OnQuit -= Cancel; - wc.CancelAsync(); - wc.Dispose(); - cancelled = true; + lock (syncObject) + { + wc.Dispose(); + wc = null; + } + } + + public void CancelAsync() + { + lock (syncObject) + if (wc != null) + wc.CancelAsync(); } } } diff --git a/OpenRA.Game/Map/MapCache.cs b/OpenRA.Game/Map/MapCache.cs index d8f07e3f77..8d521830a8 100644 --- a/OpenRA.Game/Map/MapCache.cs +++ b/OpenRA.Game/Map/MapCache.cs @@ -128,11 +128,11 @@ namespace OpenRA var url = Game.Settings.Game.MapRepository + "hash/" + string.Join(",", maps.Keys) + "/yaml"; - Action onInfoComplete = (i, cancelled) => + Action onInfoComplete = i => { - if (cancelled || i.Error != null) + if (i.Error != null) { - Log.Write("debug", "Remote map query failed with error: {0}", i.Error != null ? i.Error.Message : "cancelled"); + Log.Write("debug", "Remote map query failed with error: {0}", Download.FormatErrorMessage(i.Error)); Log.Write("debug", "URL was: {0}", url); foreach (var p in maps.Values) p.UpdateRemoteSearch(MapStatus.Unavailable, null); diff --git a/OpenRA.Game/Map/MapPreview.cs b/OpenRA.Game/Map/MapPreview.cs index 5a828b1889..2a8d46bb2e 100644 --- a/OpenRA.Game/Map/MapPreview.cs +++ b/OpenRA.Game/Map/MapPreview.cs @@ -444,13 +444,13 @@ namespace OpenRA } Action onDownloadProgress = i => { DownloadBytes = i.BytesReceived; DownloadPercentage = i.ProgressPercentage; }; - Action onDownloadComplete = (i, cancelled) => + Action onDownloadComplete = i => { download = null; - if (cancelled || i.Error != null) + if (i.Error != null) { - Log.Write("debug", "Remote map download failed with error: {0}", i.Error != null ? i.Error.Message : "cancelled"); + Log.Write("debug", "Remote map download failed with error: {0}", Download.FormatErrorMessage(i.Error)); Log.Write("debug", "URL was: {0}", mapUrl); innerData.Status = MapStatus.DownloadError; @@ -487,7 +487,7 @@ namespace OpenRA if (download == null) return; - download.Cancel(); + download.CancelAsync(); download = null; } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Installation/DownloadPackageLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Installation/DownloadPackageLogic.cs index dce2131134..3aaf2f8099 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Installation/DownloadPackageLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Installation/DownloadPackageLogic.cs @@ -115,17 +115,19 @@ namespace OpenRA.Mods.Common.Widgets.Logic retryButton.IsVisible = () => true; }); - Action onDownloadComplete = (i, cancelled) => + Action onDownloadComplete = i => { - if (i.Error != null) + if (i.Cancelled) { - onError(Download.FormatErrorMessage(i.Error)); + deleteTempFile(); + Game.RunAfterTick(Ui.CloseWindow); return; } - if (cancelled) + if (i.Error != null) { - onError("Download cancelled"); + deleteTempFile(); + onError(Download.FormatErrorMessage(i.Error)); return; } @@ -185,30 +187,30 @@ namespace OpenRA.Mods.Common.Widgets.Logic downloadHost = new Uri(url).Host; var dl = new Download(url, file, onDownloadProgress, onDownloadComplete); - cancelButton.OnClick = () => { dl.Cancel(); deleteTempFile(); Ui.CloseWindow(); }; - retryButton.OnClick = () => { dl.Cancel(); ShowDownloadDialog(); }; + cancelButton.OnClick = dl.CancelAsync; + retryButton.OnClick = ShowDownloadDialog; }; if (download.MirrorList != null) { Log.Write("install", "Fetching mirrors from " + download.MirrorList); - Action onFetchMirrorsComplete = (i, cancelled) => + Action onFetchMirrorsComplete = i => { progressBar.Indeterminate = true; + if (i.Cancelled) + { + Game.RunAfterTick(Ui.CloseWindow); + return; + } + if (i.Error != null) { onError(Download.FormatErrorMessage(i.Error)); return; } - if (cancelled) - { - onError("Download cancelled"); - return; - } - try { var data = Encoding.UTF8.GetString(i.Result); @@ -224,8 +226,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic }; var updateMirrors = new Download(download.MirrorList, onDownloadProgress, onFetchMirrorsComplete); - cancelButton.OnClick = () => { updateMirrors.Cancel(); Ui.CloseWindow(); }; - retryButton.OnClick = () => { updateMirrors.Cancel(); ShowDownloadDialog(); }; + cancelButton.OnClick = updateMirrors.CancelAsync; + retryButton.OnClick = ShowDownloadDialog; } else downloadUrl(download.URL); diff --git a/OpenRA.Mods.Common/Widgets/Logic/MainMenuLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MainMenuLogic.cs index 56b566c41d..04f1148c9e 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MainMenuLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MainMenuLogic.cs @@ -294,8 +294,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic .JoinWith("&"); new Download(newsURL, cacheFile, e => { }, - (e, c) => NewsDownloadComplete(e, cacheFile, currentNews, - () => newsButton.AttachPanel(newsPanel))); + e => NewsDownloadComplete(e, cacheFile, currentNews, + () => newsButton.AttachPanel(newsPanel))); } newsButton.OnClick = () => newsButton.AttachPanel(newsPanel); diff --git a/OpenRA.Mods.Common/Widgets/Logic/MultiplayerLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MultiplayerLogic.cs index 89a89cc753..ba4c9e02a1 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MultiplayerLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MultiplayerLogic.cs @@ -296,11 +296,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic searchStatus = SearchStatus.Fetching; - Action onComplete = (i, cancelled) => + Action onComplete = i => { currentQuery = null; - if (i.Error != null || cancelled) + if (i.Error != null) { RefreshServerListInner(null); return;