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

Commit ea265bb

Browse files
rozelegeof90
authored andcommitted
Use async void for ReactMethods instead of requeueing an async action on the native module thread. (#551)
1 parent 9396824 commit ea265bb

File tree

1 file changed

+109
-134
lines changed

1 file changed

+109
-134
lines changed

windows/CodePushNativeModule.cs

Lines changed: 109 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -53,54 +53,49 @@ public override void Initialize()
5353
}
5454

5555
[ReactMethod]
56-
public void downloadUpdate(JObject updatePackage, bool notifyProgress, IPromise promise)
56+
public async void downloadUpdate(JObject updatePackage, bool notifyProgress, IPromise promise)
5757
{
58-
Action downloadAction = async () =>
58+
try
5959
{
60-
try
61-
{
62-
updatePackage[CodePushConstants.BinaryModifiedTimeKey] = "" + await _codePush.GetBinaryResourcesModifiedTimeAsync();
63-
await _codePush.UpdateManager.DownloadPackageAsync(
64-
updatePackage,
65-
_codePush.AssetsBundleFileName,
66-
new Progress<HttpProgress>(
67-
(HttpProgress progress) =>
60+
updatePackage[CodePushConstants.BinaryModifiedTimeKey] = "" + await _codePush.GetBinaryResourcesModifiedTimeAsync();
61+
await _codePush.UpdateManager.DownloadPackageAsync(
62+
updatePackage,
63+
_codePush.AssetsBundleFileName,
64+
new Progress<HttpProgress>(
65+
(HttpProgress progress) =>
66+
{
67+
if (!notifyProgress)
6868
{
69-
if (!notifyProgress)
70-
{
71-
return;
72-
}
73-
74-
var downloadProgress = new JObject()
75-
{
76-
{ "totalBytes", progress.TotalBytesToReceive },
77-
{ "receivedBytes", progress.BytesReceived }
78-
};
79-
80-
_reactContext
81-
.GetJavaScriptModule<RCTDeviceEventEmitter>()
82-
.emit(CodePushConstants.DownloadProgressEventName, downloadProgress);
69+
return;
8370
}
84-
)
85-
);
8671

87-
JObject newPackage = await _codePush.UpdateManager.GetPackageAsync((string)updatePackage[CodePushConstants.PackageHashKey]);
88-
promise.Resolve(newPackage);
89-
}
90-
catch (InvalidDataException e)
91-
{
92-
CodePushUtils.Log(e.ToString());
93-
SettingsManager.SaveFailedUpdate(updatePackage);
94-
promise.Reject(e);
95-
}
96-
catch (Exception e)
97-
{
98-
CodePushUtils.Log(e.ToString());
99-
promise.Reject(e);
100-
}
101-
};
102-
103-
Context.RunOnNativeModulesQueueThread(downloadAction);
72+
var downloadProgress = new JObject()
73+
{
74+
{ "totalBytes", progress.TotalBytesToReceive },
75+
{ "receivedBytes", progress.BytesReceived }
76+
};
77+
78+
_reactContext
79+
.GetJavaScriptModule<RCTDeviceEventEmitter>()
80+
.emit(CodePushConstants.DownloadProgressEventName, downloadProgress);
81+
}
82+
)
83+
);
84+
85+
JObject newPackage = await _codePush.UpdateManager.GetPackageAsync((string)updatePackage[CodePushConstants.PackageHashKey]);
86+
promise.Resolve(newPackage);
87+
}
88+
catch (InvalidDataException e)
89+
{
90+
CodePushUtils.Log(e.ToString());
91+
SettingsManager.SaveFailedUpdate(updatePackage);
92+
promise.Reject(e);
93+
}
94+
catch (Exception e)
95+
{
96+
CodePushUtils.Log(e.ToString());
97+
promise.Reject(e);
98+
}
10499
}
105100

106101
[ReactMethod]
@@ -124,58 +119,53 @@ public void getConfiguration(IPromise promise)
124119
}
125120

126121
[ReactMethod]
127-
public void getUpdateMetadata(UpdateState updateState, IPromise promise)
122+
public async void getUpdateMetadata(UpdateState updateState, IPromise promise)
128123
{
129-
Action getCurrentPackageAction = async () =>
124+
JObject currentPackage = await _codePush.UpdateManager.GetCurrentPackageAsync();
125+
if (currentPackage == null)
130126
{
131-
JObject currentPackage = await _codePush.UpdateManager.GetCurrentPackageAsync();
132-
if (currentPackage == null)
133-
{
134-
promise.Resolve("");
135-
return;
136-
}
127+
promise.Resolve("");
128+
return;
129+
}
137130

138-
var currentUpdateIsPending = false;
131+
var currentUpdateIsPending = false;
139132

140-
if (currentPackage[CodePushConstants.PackageHashKey] != null)
141-
{
142-
var currentHash = (string)currentPackage[CodePushConstants.PackageHashKey];
143-
currentUpdateIsPending = SettingsManager.IsPendingUpdate(currentHash);
144-
}
133+
if (currentPackage[CodePushConstants.PackageHashKey] != null)
134+
{
135+
var currentHash = (string)currentPackage[CodePushConstants.PackageHashKey];
136+
currentUpdateIsPending = SettingsManager.IsPendingUpdate(currentHash);
137+
}
145138

146-
if (updateState == UpdateState.Pending && !currentUpdateIsPending)
147-
{
148-
// The caller wanted a pending update
149-
// but there isn't currently one.
150-
promise.Resolve("");
151-
}
152-
else if (updateState == UpdateState.Running && currentUpdateIsPending)
153-
{
154-
// The caller wants the running update, but the current
155-
// one is pending, so we need to grab the previous.
156-
promise.Resolve(await _codePush.UpdateManager.GetPreviousPackageAsync());
157-
}
158-
else
139+
if (updateState == UpdateState.Pending && !currentUpdateIsPending)
140+
{
141+
// The caller wanted a pending update
142+
// but there isn't currently one.
143+
promise.Resolve("");
144+
}
145+
else if (updateState == UpdateState.Running && currentUpdateIsPending)
146+
{
147+
// The caller wants the running update, but the current
148+
// one is pending, so we need to grab the previous.
149+
promise.Resolve(await _codePush.UpdateManager.GetPreviousPackageAsync());
150+
}
151+
else
152+
{
153+
// The current package satisfies the request:
154+
// 1) Caller wanted a pending, and there is a pending update
155+
// 2) Caller wanted the running update, and there isn't a pending
156+
// 3) Caller wants the latest update, regardless if it's pending or not
157+
if (_codePush.IsRunningBinaryVersion)
159158
{
160-
// The current package satisfies the request:
161-
// 1) Caller wanted a pending, and there is a pending update
162-
// 2) Caller wanted the running update, and there isn't a pending
163-
// 3) Caller wants the latest update, regardless if it's pending or not
164-
if (_codePush.IsRunningBinaryVersion)
165-
{
166-
// This only matters in Debug builds. Since we do not clear "outdated" updates,
167-
// we need to indicate to the JS side that somehow we have a current update on
168-
// disk that is not actually running.
169-
currentPackage["_isDebugOnly"] = true;
170-
}
171-
172-
// Enable differentiating pending vs. non-pending updates
173-
currentPackage["isPending"] = currentUpdateIsPending;
174-
promise.Resolve(currentPackage);
159+
// This only matters in Debug builds. Since we do not clear "outdated" updates,
160+
// we need to indicate to the JS side that somehow we have a current update on
161+
// disk that is not actually running.
162+
currentPackage["_isDebugOnly"] = true;
175163
}
176-
};
177164

178-
Context.RunOnNativeModulesQueueThread(getCurrentPackageAction);
165+
// Enable differentiating pending vs. non-pending updates
166+
currentPackage["isPending"] = currentUpdateIsPending;
167+
promise.Resolve(currentPackage);
168+
}
179169
}
180170

181171

@@ -187,39 +177,34 @@ public void getNewStatusReport(IPromise promise)
187177
}
188178

189179
[ReactMethod]
190-
public void installUpdate(JObject updatePackage, InstallMode installMode, int minimumBackgroundDuration, IPromise promise)
180+
public async void installUpdate(JObject updatePackage, InstallMode installMode, int minimumBackgroundDuration, IPromise promise)
191181
{
192-
Action installUpdateAction = async () =>
182+
await _codePush.UpdateManager.InstallPackageAsync(updatePackage, SettingsManager.IsPendingUpdate(null));
183+
var pendingHash = (string)updatePackage[CodePushConstants.PackageHashKey];
184+
SettingsManager.SavePendingUpdate(pendingHash, /* isLoading */false);
185+
if (installMode == InstallMode.OnNextResume)
193186
{
194-
await _codePush.UpdateManager.InstallPackageAsync(updatePackage, SettingsManager.IsPendingUpdate(null));
195-
var pendingHash = (string)updatePackage[CodePushConstants.PackageHashKey];
196-
SettingsManager.SavePendingUpdate(pendingHash, /* isLoading */false);
197-
if (installMode == InstallMode.OnNextResume)
187+
if (_minimumBackgroundListener == null)
198188
{
199-
if (_minimumBackgroundListener == null)
189+
// Ensure we do not add the listener twice.
190+
Action loadBundleAction = () =>
200191
{
201-
// Ensure we do not add the listener twice.
202-
Action loadBundleAction = () =>
192+
Context.RunOnNativeModulesQueueThread(async () =>
203193
{
204-
Context.RunOnNativeModulesQueueThread(async () =>
205-
{
206-
await LoadBundleAsync();
207-
});
208-
};
194+
await LoadBundleAsync();
195+
});
196+
};
209197

210-
_minimumBackgroundListener = new MinimumBackgroundListener(loadBundleAction, minimumBackgroundDuration);
211-
_reactContext.AddLifecycleEventListener(_minimumBackgroundListener);
212-
}
213-
else
214-
{
215-
_minimumBackgroundListener.MinimumBackgroundDuration = minimumBackgroundDuration;
216-
}
198+
_minimumBackgroundListener = new MinimumBackgroundListener(loadBundleAction, minimumBackgroundDuration);
199+
_reactContext.AddLifecycleEventListener(_minimumBackgroundListener);
217200
}
201+
else
202+
{
203+
_minimumBackgroundListener.MinimumBackgroundDuration = minimumBackgroundDuration;
204+
}
205+
}
218206

219-
promise.Resolve("");
220-
};
221-
222-
Context.RunOnNativeModulesQueueThread(installUpdateAction);
207+
promise.Resolve("");
223208
}
224209

225210
[ReactMethod]
@@ -229,18 +214,13 @@ public void isFailedUpdate(string packageHash, IPromise promise)
229214
}
230215

231216
[ReactMethod]
232-
public void isFirstRun(string packageHash, IPromise promise)
217+
public async void isFirstRun(string packageHash, IPromise promise)
233218
{
234-
Action isFirstRunAction = async () =>
235-
{
236-
bool isFirstRun = _codePush.DidUpdate
237-
&& packageHash != null
238-
&& packageHash.Length > 0
239-
&& packageHash.Equals(await _codePush.UpdateManager.GetCurrentPackageHashAsync());
240-
promise.Resolve(isFirstRun);
241-
};
242-
243-
Context.RunOnNativeModulesQueueThread(isFirstRunAction);
219+
bool isFirstRun = _codePush.DidUpdate
220+
&& packageHash != null
221+
&& packageHash.Length > 0
222+
&& packageHash.Equals(await _codePush.UpdateManager.GetCurrentPackageHashAsync());
223+
promise.Resolve(isFirstRun);
244224
}
245225

246226
[ReactMethod]
@@ -251,19 +231,14 @@ public void notifyApplicationReady(IPromise promise)
251231
}
252232

253233
[ReactMethod]
254-
public void restartApp(bool onlyIfUpdateIsPending)
234+
public async void restartApp(bool onlyIfUpdateIsPending)
255235
{
256-
Action restartAppAction = async () =>
236+
// If this is an unconditional restart request, or there
237+
// is current pending update, then reload the app.
238+
if (!onlyIfUpdateIsPending || SettingsManager.IsPendingUpdate(null))
257239
{
258-
// If this is an unconditional restart request, or there
259-
// is current pending update, then reload the app.
260-
if (!onlyIfUpdateIsPending || SettingsManager.IsPendingUpdate(null))
261-
{
262-
await LoadBundleAsync();
263-
}
264-
};
265-
266-
Context.RunOnNativeModulesQueueThread(restartAppAction);
240+
await LoadBundleAsync();
241+
}
267242
}
268243

269244
internal async Task LoadBundleAsync()

0 commit comments

Comments
 (0)