Skip to content

Commit f4d545a

Browse files
committedAug 31, 2018
Merge branch 'release/0.9.6'
2 parents 1bb2ab3 + 4d221ce commit f4d545a

File tree

81 files changed

+3141
-4809
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+3141
-4809
lines changed
 

‎CHANGELOG.md

+18-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,24 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/); this project adheres to [Semantic Versioning](http://semver.org/).
55

66
-----------------------
7-
## [0.9.5] - unreleased
7+
## [0.9.6] - unreleased
8+
9+
### Added
10+
- Added `Play`/`Wait` extension methods for `Animation` and `Animator`.
11+
- Added `AsyncResult.IsStarted` helper property.
12+
13+
### Changed
14+
- Changed `AsyncResult` constructors argument order to avoid ambiguity in some cases.
15+
- Moved the package content to Plugins folder and remove assembly definition file.
16+
- Moved web request related helpers from `AsyncUtility` to `AsyncWww` class.
17+
- Changed `AsyncUtility.SendToMainThread`, `AsyncUtility.PostToMainThread` and `AsyncUtility.InvokeOnMainThread` implementation to use `ConcurrentQueue` for net46+ to avoid unnesesary locks.
18+
- Changed interface of `AsyncResultQueue`.
19+
20+
### Removed
21+
- Removed `IAsyncOperationEvents.TryAddCompletionCallback` and `IAsyncOperationEvents.TryAddProgressCallback` methods. These methods are not needed in 99% of cases and may lead to logic errors in multi-threaded environment.
22+
23+
-----------------------
24+
## [0.9.5] - 2018.07.31
825

926
### Added
1027
- Added `IAsyncOperation.Id` property for easy operation identification.

‎README.md

+47-25
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Channel | UnityFx.Async |
55
AppVeyor | [![Build status](https://ci.appveyor.com/api/projects/status/hfmq9vow53al7tpd/branch/master?svg=true)](https://ci.appveyor.com/project/Arvtesh/unityfx-async/branch/master) [![AppVeyor tests](https://img.shields.io/appveyor/tests/Arvtesh/unityFx-async.svg)](https://ci.appveyor.com/project/Arvtesh/unityfx-async/build/tests)
66
NuGet | [![NuGet](https://img.shields.io/nuget/v/UnityFx.Async.svg)](https://www.nuget.org/packages/UnityFx.Async)
77
Github | [![GitHub release](https://img.shields.io/github/release/Arvtesh/UnityFx.Async.svg?logo=github)](https://github.com/Arvtesh/UnityFx.Async/releases)
8-
Unity Asset Store | [![Asynchronous operations for Unity](https://img.shields.io/badge/tools-v0.9.5-green.svg)](https://assetstore.unity.com/packages/tools/asynchronous-operations-for-unity-96696)
8+
Unity Asset Store | [![Asynchronous operations for Unity](https://img.shields.io/badge/tools-v0.9.6-green.svg)](https://assetstore.unity.com/packages/tools/asynchronous-operations-for-unity-96696)
99

1010
**If you enjoy using the library - please, [rate and review](https://assetstore.unity.com/packages/tools/asynchronous-operations-for-unity-96696) it on the Asset Store!**
1111

@@ -156,7 +156,7 @@ catch (Exception e)
156156
```
157157
In fact the only notable difference from synchronous implementation is usage of the mentioned `async` and `await` keywords. It's worth mentioning that a lot of hidden work is done by both the C# compliter and asynchronous operation to allow this.
158158

159-
*UnityFx.Async* supports all of the asynchronous programming approaches described.
159+
*UnityFx.Async* supports all the asynchronous programming approaches described.
160160

161161
## Using the library
162162
Reference the DLL and import the namespace:
@@ -166,22 +166,26 @@ using UnityFx.Async.Promises; // For promises-specific stuff.
166166
```
167167
Create an operation instance like this:
168168
```csharp
169-
var op = new AsyncCompletionSource<string>();
169+
var acs = new AsyncCompletionSource<string>();
170+
var op = acs.Operation;
170171
```
171172
The type of the operation should reflect its result type. In this case we create a special kind of operation - a completion source, that incapsulates both producer and consumer interfaces (consumer side is represented via `IAsyncOperation` / `IAsyncOperation<TResult>` interfaces and producer side is `IAsyncCompletionSource` / `IAsyncCompletionSource<TResult>`, `AsyncCompletionSource` implements both of the interfaces).
172173

173-
While operation is running its progress can be set like this:
174+
While operation is running its progress can be set via `IAsyncCompletionSource` like this:
174175
```csharp
175-
op.SetProgress(progressValue);
176+
acs.SetProgress(progressValue);
176177
```
177178

178-
Upon completion of an asynchronous operation transition it to one of the final states (`RanToCompletion`, `Faulted` or `Canceled`):
179+
Cancellation can be requested for any operation at any time (note that this call just *requests* cancellation, specific operation implementation may decide to postpone or even ignore it):
179180
```csharp
180-
op.SetResult(resultValue);
181+
op.Cancel();
181182
```
182-
Or, if the operation has failed:
183+
184+
Upon completion an asynchronous operation transitions to one of the final states (`RanToCompletion`, `Faulted` or `Canceled`):
183185
```csharp
184-
op.SetException(ex);
186+
acs.SetResult(resultValue); // Sets result value and transitions to RanToCompletion state.
187+
acs.SetException(ex); // Transitions the operation to Faulted state.
188+
acs.SetCanceled(); // Transitions the operation to Canceled state.
185189
```
186190

187191
To see it in context, here is an example of a function that downloads text from URL using [UnityWebRequest](https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequest.html):
@@ -290,7 +294,7 @@ DownloadTextAsync("http://www.google.com")
290294
.Then(text => ExtractFirstUrl(text))
291295
.Rebind(url => new Url(url));
292296
```
293-
`ContinueWith()` and `Finally()` delegates get called independently of the antecedent operation result. `ContinueWith()` also define overloads accepting `AsyncContinuationOptions` argument that allows to customize its behaviour. Note that `ContinueWith()` is analog to the corresponding [Task method](https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.continuewith) and not a part of the JS promise pattern:
297+
`ContinueWith()` and `Finally()` delegates get called independently of the antecedent operation result. `ContinueWith()` also define overloads accepting `AsyncContinuationOptions` argument that allows to customize its behaviour. Note that `ContinueWith()` matches the corresponding [Task method](https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.continuewith) and is not a part of the JS promise pattern:
294298
```csharp
295299
DownloadTextAsync("http://www.google.com")
296300
.ContinueWith(op => Debug.Log("1"))
@@ -325,43 +329,43 @@ finally
325329
### Cancellation
326330
All library operations can be cancelled using `Cancel()` method:
327331
```csharp
328-
op.Cancel(); // attempts to cancel an operation
332+
op.Cancel(); // Attempts to cancel an operation.
329333
```
330-
Or with `WithCancellation()` extension:
334+
Or with `WithCancellation()` extension (if [CancellationToken](https://docs.microsoft.com/en-us/dotnet/api/system.threading.cancellationtoken) is needed):
331335
```csharp
332336
DownloadTextAsync("http://www.google.com")
333337
.Then(text => ExtractFirstParagraph(text))
334338
.WithCancellation(cancellationToken);
335339
```
336-
If the [token](https://docs.microsoft.com/en-us/dotnet/api/system.threading.cancellationtoken) passed to `WithCancellation()` is cancelled, the target operation is cancelled as well (and that means cancelling all chained operations) as soon as possible. Cancellation might not be instant (depends on specific operation implementation). Also, please note that not all operations might support cancellation; in this case `Cancel()` will throw `NotSupportedException`.
340+
If the [token](https://docs.microsoft.com/en-us/dotnet/api/system.threading.cancellationtoken) passed to `WithCancellation()` is cancelled, the target operation is cancelled as well (and that means cancelling all chained operations) as soon as possible. Cancellation might not be instant (depends on specific operation implementation). Also, please note that not all operations might support cancellation; in this case `Cancel()` might just do nothing.
337341

338342
### Progress reporting
339343
Library operations support progress reporting via exposing `IAsyncOperation.Progress` property and progress reporting events:
340344
```csharp
341-
var progress = op.Progress; // gets an operation progress as a float value in range [0, 1]
345+
var progress = op.Progress; // Gets an operation progress as a float value in range [0, 1].
342346
343-
// subscribe to progress changed event
347+
// Subscribe to progress changed event.
344348
op.ProgressChanged += (sender, args) =>
345349
{
346350
Debug.Log("Progress = " + args.ProgressPercentage);
347351
}
348352

349-
// add progress changed delegate
353+
// Add progress changed delegate.
350354
op.AddProgressCallback(op =>
351355
{
352356
Debug.Log("Progress = " + op.Progress);
353357
});
354358
```
355-
There is `AsyncResult.GetProgress()` virtual method that is called when a progress values is requested. Finally there are producer-side methods like `AsyncCompletionSource.TrySetProgress()` that can set the progress value.
359+
There is `AsyncResult.GetProgress()` virtual method that is called when a progress values is requested. Finally there are producer-side methods like `AsyncCompletionSource.SetProgress()` that can set the progress value.
356360

357361
### Synchronization context capturing
358362
The default behaviour of all library methods is to capture current [SynchronizationContext](https://docs.microsoft.com/en-us/dotnet/api/system.threading.synchronizationcontext) and try to schedule continuations on it. If there is no synchronization context attached to current thread, continuations are executed on a thread that initiated an operation completion. The same behaviour applies to `async` / `await` implementation unless explicitly overriden with `ConfigureAwait()`:
359363
```csharp
360364
// thread1
361365
await DownloadTextAsync("http://www.google.com");
362-
// Back on thread1
366+
// Back on thread1.
363367
await DownloadTextAsync("http://www.yahoo.com").ConfigureAwait(false);
364-
// Most likely some other thread
368+
// Most likely some other thread.
365369
```
366370

367371
### Completion callbacks
@@ -401,7 +405,7 @@ All operations implement [IDisposable](https://docs.microsoft.com/en-us/dotnet/a
401405
Please note that `Dispose()` implementation is NOT thread-safe and can only be called after an operation has completed (the same restrictions apply to [Task](https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task)).
402406

403407
### Completed asynchronous operations
404-
There are a number of helper methods for creating completed operations:
408+
There are a number of helper methods and properties for creating completed operations:
405409
```csharp
406410
var op1 = AsyncResult.CompletedOperation;
407411
var op2 = AsyncResult.CanceledOperation;
@@ -427,10 +431,10 @@ var op5 = unityWWW.ToAsync();
427431

428432
### Creating own asynchronous operations
429433
Most common way of creating own asynchronous operation is instantiating `AsyncCompletionSource` instance and call `SetResult()` / `SetException()` / `SetCanceled()` when done. Still there are cases when more control is required. For this purpose the library provides two public extendable implementations for asynchronous operations:
430-
* `AsyncResult`: a generic asynchronous operation without a result value.
434+
* `AsyncResult`: an asynchronous operation without a result value.
431435
* `AsyncResult<TResult>`: an asynchronous operation with a result value.
432436

433-
The sample code below demostrates creating a delay operation:
437+
The sample code below demostrates creating a delay operation (in fact library provides one, this is just a simplified example):
434438
```csharp
435439
public class TimerDelayResult : AsyncResult
436440
{
@@ -469,6 +473,27 @@ public class TimerDelayResult : AsyncResult
469473
}
470474
```
471475

476+
### Unity3d helpers
477+
The library consists of 3 major parts:
478+
* Core tools (defined in `UnityFx.Async.dll` assembly, do not depend on Unity3d);
479+
* Unity3d-specific tools (defined as a collection of C# scripts located in `Assets/Plugins/UnityFx.Async` if installed as an Asset Store package, require Unity3d to compile/execute).
480+
* Unity3d samples (defined as a collection of C# scripts located in `Assets/UnityFx.Async` if installed as an Asset Store package, require Unity3d to compile/execute).
481+
482+
Everything described before (unless specified otherwise) does not require Unity and can be used in any application. The Unity-specific stuff is located in 3 classes:
483+
* `AsyncUtility`. Defines helper methods for accessing main thread in Unity, running coroutines without actually using a `MonoBehaviour` and waiting for native Unity asynchronous operations outside of coroutines.
484+
* `AsyncWww`. Defines web request related helpers.
485+
* `UnityExtensions`. Defines extensions for native Unity classes (like `AsyncOperation` and `UnityWebRequest`).
486+
487+
For example, one can throw a few lines of code to be executed on a main thread using:
488+
```csharp
489+
// Sends a delegate to the main thread and blocks calling thread until it is executed.
490+
AsyncUtility.SendToMainThread(args => Debug.Log("On the main thread."), null);
491+
// Posts a delegate to the main thread and returns immediately. Returns an asynchronous operation that can be used to track the delegate execution.
492+
AsyncUtility.PostToMainThread(args => Debug.Log("On the main thread."), null);
493+
// If calling thread is the main thread executes the delegate synchronously, otherwise posts it to the main thread. Returns an asynchronous operation that can be used to track the delegate execution.
494+
AsyncUtility.InvokeOnMainThread(args => Debug.Log("On the main thread."), null);
495+
```
496+
472497
## Comparison to .NET Tasks
473498
The comparison table below shows how *UnityFx.Async* entities relate to [Tasks](https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task):
474499

@@ -515,15 +540,12 @@ Please see the links below for extended information on the product:
515540
- [Unity coroutines](https://docs.unity3d.com/Manual/Coroutines.html).
516541

517542
## Contributing
518-
519543
Please see [contributing guide](.github/CONTRIBUTING.md) for details.
520544

521545
## Versioning
522-
523546
The project uses [SemVer](https://semver.org/) versioning pattern. For the versions available, see [tags in this repository](https://github.com/Arvtesh/UnityFx.Async/tags).
524547

525548
## License
526-
527549
Please see the [![license](https://img.shields.io/github/license/Arvtesh/UnityFx.Async.svg)](LICENSE.md) for details.
528550

529551
## Acknowledgments

0 commit comments

Comments
 (0)
Please sign in to comment.