Skip to content
This repository was archived by the owner on May 20, 2025. It is now read-only.

Commit b72bf77

Browse files
committed
fix(async): Changing all await calls to .ConfigureAwait(false)
The async calls in CodePush for ReactWindows can all be executed on any background thread, so adding .ConfigureAwait(false) can improve performance and reduce the likelihood of deadlock. The blocking calls in `InitializeUpdateAfterRestart()` were hanging, but now that .ConfigureAwait(false) is used pervasively, it is no longer a problem. Fixes #550
1 parent 032df75 commit b72bf77

File tree

6 files changed

+99
-99
lines changed

6 files changed

+99
-99
lines changed

windows/CodePushNativeModule.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public async void downloadUpdate(JObject updatePackage, bool notifyProgress, IPr
5757
{
5858
try
5959
{
60-
updatePackage[CodePushConstants.BinaryModifiedTimeKey] = "" + await _codePush.GetBinaryResourcesModifiedTimeAsync();
60+
updatePackage[CodePushConstants.BinaryModifiedTimeKey] = "" + await _codePush.GetBinaryResourcesModifiedTimeAsync().ConfigureAwait(false);
6161
await _codePush.UpdateManager.DownloadPackageAsync(
6262
updatePackage,
6363
_codePush.AssetsBundleFileName,
@@ -80,9 +80,9 @@ await _codePush.UpdateManager.DownloadPackageAsync(
8080
.emit(CodePushConstants.DownloadProgressEventName, downloadProgress);
8181
}
8282
)
83-
);
83+
).ConfigureAwait(false);
8484

85-
JObject newPackage = await _codePush.UpdateManager.GetPackageAsync((string)updatePackage[CodePushConstants.PackageHashKey]);
85+
JObject newPackage = await _codePush.UpdateManager.GetPackageAsync((string)updatePackage[CodePushConstants.PackageHashKey]).ConfigureAwait(false);
8686
promise.Resolve(newPackage);
8787
}
8888
catch (InvalidDataException e)
@@ -121,7 +121,7 @@ public void getConfiguration(IPromise promise)
121121
[ReactMethod]
122122
public async void getUpdateMetadata(UpdateState updateState, IPromise promise)
123123
{
124-
JObject currentPackage = await _codePush.UpdateManager.GetCurrentPackageAsync();
124+
JObject currentPackage = await _codePush.UpdateManager.GetCurrentPackageAsync().ConfigureAwait(false);
125125
if (currentPackage == null)
126126
{
127127
promise.Resolve("");
@@ -146,7 +146,7 @@ public async void getUpdateMetadata(UpdateState updateState, IPromise promise)
146146
{
147147
// The caller wants the running update, but the current
148148
// one is pending, so we need to grab the previous.
149-
promise.Resolve(await _codePush.UpdateManager.GetPreviousPackageAsync());
149+
promise.Resolve(await _codePush.UpdateManager.GetPreviousPackageAsync().ConfigureAwait(false));
150150
}
151151
else
152152
{
@@ -179,7 +179,7 @@ public void getNewStatusReport(IPromise promise)
179179
[ReactMethod]
180180
public async void installUpdate(JObject updatePackage, InstallMode installMode, int minimumBackgroundDuration, IPromise promise)
181181
{
182-
await _codePush.UpdateManager.InstallPackageAsync(updatePackage, SettingsManager.IsPendingUpdate(null));
182+
await _codePush.UpdateManager.InstallPackageAsync(updatePackage, SettingsManager.IsPendingUpdate(null)).ConfigureAwait(false);
183183
var pendingHash = (string)updatePackage[CodePushConstants.PackageHashKey];
184184
SettingsManager.SavePendingUpdate(pendingHash, /* isLoading */false);
185185
if (installMode == InstallMode.OnNextResume)
@@ -191,7 +191,7 @@ public async void installUpdate(JObject updatePackage, InstallMode installMode,
191191
{
192192
Context.RunOnNativeModulesQueueThread(async () =>
193193
{
194-
await LoadBundleAsync();
194+
await LoadBundleAsync().ConfigureAwait(false);
195195
});
196196
};
197197

@@ -219,7 +219,7 @@ public async void isFirstRun(string packageHash, IPromise promise)
219219
bool isFirstRun = _codePush.DidUpdate
220220
&& packageHash != null
221221
&& packageHash.Length > 0
222-
&& packageHash.Equals(await _codePush.UpdateManager.GetCurrentPackageHashAsync());
222+
&& packageHash.Equals(await _codePush.UpdateManager.GetCurrentPackageHashAsync().ConfigureAwait(false));
223223
promise.Resolve(isFirstRun);
224224
}
225225

@@ -237,7 +237,7 @@ public async void restartApp(bool onlyIfUpdateIsPending)
237237
// is current pending update, then reload the app.
238238
if (!onlyIfUpdateIsPending || SettingsManager.IsPendingUpdate(null))
239239
{
240-
await LoadBundleAsync();
240+
await LoadBundleAsync().ConfigureAwait(false);
241241
}
242242
}
243243

@@ -254,7 +254,7 @@ internal async Task LoadBundleAsync()
254254

255255
// #2) Update the locally stored JS bundle file path
256256
Type reactInstanceManagerType = typeof(ReactInstanceManager);
257-
string latestJSBundleFile = await _codePush.GetJavaScriptBundleFileAsync(_codePush.AssetsBundleFileName);
257+
string latestJSBundleFile = await _codePush.GetJavaScriptBundleFileAsync(_codePush.AssetsBundleFileName).ConfigureAwait(false);
258258
reactInstanceManagerType
259259
.GetField("_jsBundleFile", BindingFlags.NonPublic | BindingFlags.Instance)
260260
.SetValue(reactInstanceManager, latestJSBundleFile);

windows/CodePushReactPackage.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ public async Task<string> GetJavaScriptBundleFileAsync(string assetsBundleFileNa
8585
{
8686
AssetsBundleFileName = assetsBundleFileName;
8787
string binaryJsBundleUrl = CodePushConstants.AssetsBundlePrefix + assetsBundleFileName;
88-
var binaryResourcesModifiedTime = await GetBinaryResourcesModifiedTimeAsync();
89-
var packageFile = await UpdateManager.GetCurrentPackageBundleAsync(AssetsBundleFileName);
88+
var binaryResourcesModifiedTime = await GetBinaryResourcesModifiedTimeAsync().ConfigureAwait(false);
89+
var packageFile = await UpdateManager.GetCurrentPackageBundleAsync(AssetsBundleFileName).ConfigureAwait(false);
9090
if (packageFile == null)
9191
{
9292
// There has not been any downloaded updates.
@@ -95,7 +95,7 @@ public async Task<string> GetJavaScriptBundleFileAsync(string assetsBundleFileNa
9595
return binaryJsBundleUrl;
9696
}
9797

98-
var packageMetadata = await UpdateManager.GetCurrentPackageAsync();
98+
var packageMetadata = await UpdateManager.GetCurrentPackageAsync().ConfigureAwait(false);
9999
long? binaryModifiedDateDuringPackageInstall = null;
100100
var binaryModifiedDateDuringPackageInstallString = (string)packageMetadata[CodePushConstants.BinaryModifiedTimeKey];
101101
if (binaryModifiedDateDuringPackageInstallString != null)
@@ -119,7 +119,7 @@ public async Task<string> GetJavaScriptBundleFileAsync(string assetsBundleFileNa
119119
DidUpdate = false;
120120
if (!MainPage.UseDeveloperSupport || !AppVersion.Equals(packageAppVersion))
121121
{
122-
await ClearUpdatesAsync();
122+
await ClearUpdatesAsync().ConfigureAwait(false);
123123
}
124124

125125
CodePushUtils.LogBundleUrl(binaryJsBundleUrl);
@@ -134,8 +134,8 @@ public async Task<string> GetJavaScriptBundleFileAsync(string assetsBundleFileNa
134134

135135
internal async Task<long> GetBinaryResourcesModifiedTimeAsync()
136136
{
137-
var assetJSBundleFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri(CodePushConstants.AssetsBundlePrefix + AssetsBundleFileName));
138-
var fileProperties = await assetJSBundleFile.GetBasicPropertiesAsync();
137+
var assetJSBundleFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri(CodePushConstants.AssetsBundlePrefix + AssetsBundleFileName)).AsTask().ConfigureAwait(false);
138+
var fileProperties = await assetJSBundleFile.GetBasicPropertiesAsync().AsTask().ConfigureAwait(false);
139139
return fileProperties.DateModified.ToUnixTimeMilliseconds();
140140
}
141141

@@ -170,7 +170,7 @@ internal void InitializeUpdateAfterRestart()
170170

171171
internal async Task ClearUpdatesAsync()
172172
{
173-
await UpdateManager.ClearUpdatesAsync();
173+
await UpdateManager.ClearUpdatesAsync().ConfigureAwait(false);
174174
SettingsManager.RemovePendingUpdate();
175175
SettingsManager.RemoveFailedUpdates();
176176
}
@@ -181,18 +181,18 @@ internal async Task ClearUpdatesAsync()
181181

182182
private async Task ClearReactDevBundleCacheAsync()
183183
{
184-
var devBundleCacheFile = (StorageFile) await ApplicationData.Current.LocalFolder.TryGetItemAsync(CodePushConstants.ReactDevBundleCacheFileName);
184+
var devBundleCacheFile = (StorageFile)await ApplicationData.Current.LocalFolder.TryGetItemAsync(CodePushConstants.ReactDevBundleCacheFileName).AsTask().ConfigureAwait(false);
185185
if (devBundleCacheFile != null)
186186
{
187-
await devBundleCacheFile.DeleteAsync();
187+
await devBundleCacheFile.DeleteAsync().AsTask().ConfigureAwait(false);
188188
}
189189
}
190190

191191
private async Task RollbackPackageAsync()
192192
{
193-
JObject failedPackage = await UpdateManager.GetCurrentPackageAsync();
193+
JObject failedPackage = await UpdateManager.GetCurrentPackageAsync().ConfigureAwait(false);
194194
SettingsManager.SaveFailedUpdate(failedPackage);
195-
await UpdateManager.RollbackPackageAsync();
195+
await UpdateManager.RollbackPackageAsync().ConfigureAwait(false);
196196
SettingsManager.RemovePendingUpdate();
197197
}
198198

windows/CodePushUtils.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ internal class CodePushUtils
1212
{
1313
internal async static Task<JObject> GetJObjectFromFileAsync(StorageFile file)
1414
{
15-
string jsonString = await FileIO.ReadTextAsync(file);
15+
string jsonString = await FileIO.ReadTextAsync(file).AsTask().ConfigureAwait(false);
1616
if (jsonString.Length == 0)
1717
{
1818
return new JObject();

windows/FileUtils.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ internal class FileUtils
88
{
99
internal async static Task MergeFoldersAsync(StorageFolder source, StorageFolder target)
1010
{
11-
foreach (StorageFile sourceFile in await source.GetFilesAsync())
11+
foreach (StorageFile sourceFile in await source.GetFilesAsync().AsTask().ConfigureAwait(false))
1212
{
13-
await sourceFile.CopyAndReplaceAsync(await target.CreateFileAsync(sourceFile.Name, CreationCollisionOption.OpenIfExists));
13+
await sourceFile.CopyAndReplaceAsync(await target.CreateFileAsync(sourceFile.Name, CreationCollisionOption.OpenIfExists).AsTask().ConfigureAwait(false)).AsTask().ConfigureAwait(false);
1414
}
1515

16-
foreach (StorageFolder sourceDirectory in await source.GetFoldersAsync())
16+
foreach (StorageFolder sourceDirectory in await source.GetFoldersAsync().AsTask().ConfigureAwait(false))
1717
{
18-
StorageFolder nextTargetSubDir = await target.CreateFolderAsync(sourceDirectory.Name, CreationCollisionOption.OpenIfExists);
19-
await MergeFoldersAsync(sourceDirectory, nextTargetSubDir);
18+
StorageFolder nextTargetSubDir = await target.CreateFolderAsync(sourceDirectory.Name, CreationCollisionOption.OpenIfExists).AsTask().ConfigureAwait(false);
19+
await MergeFoldersAsync(sourceDirectory, nextTargetSubDir).ConfigureAwait(false);
2020
}
2121
}
2222
}

0 commit comments

Comments
 (0)