Compare commits

...

109 Commits
2.3.1 ... 2.4.1

Author SHA1 Message Date
github-actions[bot]
cfe509a556 feat: Update package.json to 2.4.1 2023-09-21 03:22:58 +00:00
hadashiA
a46a4cac01 Merge pull request #509 from Cysharp/ku/fix-dotween-registration
Fix a bug in Dotween after returning to the pool of `CancellationToken.Register`
2023-09-21 12:20:43 +09:00
hadashiA
3ed28e534a Tweaks 2023-09-21 10:00:27 +09:00
hadashiA
be8dbe8804 Fixed a bug in Dotween after returning to the pool of CancellationToken.Register 2023-09-20 17:35:04 +09:00
github-actions[bot]
64f7eec4e9 feat: Update package.json to 2.4.0 2023-09-14 07:43:41 +00:00
hadashiA
3a93f4a49f Update README.md 2023-09-14 16:40:42 +09:00
hadashiA
71958adc3d Merge pull request #498 from Cysharp/hadashiA/async-linq-merge
Add UniTaskAsyncEnumerable.Merge
2023-09-14 16:28:05 +09:00
hadashiA
acc71550c9 Merge pull request #496 from Cysharp/hadashiA/awaitable
Add EndOfFrame implementation using `UnityEngine.Awaitable`
2023-09-14 16:26:40 +09:00
hadashiA
3ba64412f8 Reduce the lock 2023-09-14 16:26:13 +09:00
hadashiA
90c5e5a6ad Merge pull request #500 from Cysharp/hadashiA/inner-ex2
Use always innerException for Task.AsUniTask
2023-09-14 16:22:09 +09:00
hadashiA
8a022ee02d Merge pull request #499 from Cysharp/hadashiA/fix-completion-source-retval
Fix conditions for UniTaskCompletionSourceCore.TrySet* to be true
2023-09-14 16:12:32 +09:00
hadashiA
6a89ea8139 Merge pull request #503 from Cysharp/hadashiA/fix-auto-reset-source
Add check to that AutoResetUniTaskSource already returned to the pool
2023-09-14 16:10:42 +09:00
hadashiA
90c81613ac Add check to that innerException is empty 2023-09-14 16:08:32 +09:00
hadashiA
7c62904a74 Merge pull request #489 from Merglasch/EarlyInit
Earlier intialization for Unitask, depending on unity version
2023-09-14 15:43:34 +09:00
hadashiA
4f6344a12f Add check to AutoResetUniTaskSource already returned to the pool 2023-09-14 10:36:31 +09:00
hadashiA
937d3adf66 Fix race condition 2023-09-12 14:34:53 +09:00
hadashiA
3bac16229f Reduce lock 2023-09-11 00:22:21 +09:00
hadashiA
ea57847c97 Add dispose 2023-09-09 17:04:02 +09:00
hadashiA
730d68132d Tweaks 2023-09-09 14:27:06 +09:00
hadashiA
6db872236e Fix test 2023-09-09 10:16:01 +09:00
hadashiA
ba7e676c6f Fix test 2023-09-09 10:01:58 +09:00
hadashiA
6e99accf99 Fix race condition (todo: too wide lock range?) 2023-09-09 08:49:52 +09:00
hadashiA
b195df9773 Update README 2023-09-08 20:06:02 +09:00
hadashiA
f303d9d7e8 Add UniTaskAsyncEnumerable.Merge 2023-09-08 20:05:51 +09:00
hadashiA
62a2a2e8f9 Use always innerException for Task.AsUniTask 2023-09-08 18:43:41 +09:00
hadashiA
ffbadbcc4c Update README about WaitForEndOfFrame 2023-09-08 18:00:39 +09:00
hadashiA
50ad2ee9d6 Fix conditions for UniTaskCompletionSourceCore.TrySet* to be true 2023-09-08 17:31:19 +09:00
hadashiA
c170af5642 Merge pull request #487 from Cysharp/hadashiA/fix-test
Fix TriggerEvent problem with iterate breaking on Remove when it has multiple handlers
2023-09-08 17:22:16 +09:00
hadashiA
242bceecd3 Merge pull request #492 from Cysharp/hadashiA/readme
Update README about DOTween
2023-09-08 17:19:30 +09:00
hadashiA
06346b8a2a Merge pull request #493 from Cysharp/hadashiA/monitor
Reduce the times of AwakeMonitor checking
2023-09-08 17:18:50 +09:00
hadashiA
b071eeadfb Merge pull request #486 from Cysharp/hadashiA/inner-ex
Use innerException for `Task.AsUniTask`
2023-09-08 17:17:28 +09:00
hadashiA
e7f23d8328 Merge pull request #497 from Cysharp/hadashiA/net6
Use dotnet >= 6.0
2023-09-08 17:16:36 +09:00
hadashiA
47a3f09abf Merge pull request #485 from Cysharp/hadashiA/fix-dotween
Fix a problem in dotween where an extra update would run after canceling
2023-09-08 17:16:20 +09:00
hadashiA
a7a6af0a68 Fix AwakeMonitor to not duplicates 2023-09-08 09:36:42 +09:00
hadashiA
f203b6c051 Merge pull request #494 from Cysharp/hadashiA/web-req-null-check
Add check if UnityWebRequest was destroyed
2023-09-07 18:13:46 +09:00
hadashiA
07211f1fc3 Bump dotnet version to 6.0/7.0 2023-09-07 18:12:47 +09:00
hadashiA
bc27f6c0d8 Fix test 2023-09-07 17:43:40 +09:00
hadashiA
c65f9c3497 Add EndOfFrame implementation using UnityEngine.Awaitable 2023-09-07 17:36:06 +09:00
hadashiA
afe5f57adc Use CancellationToken.Register to cancel DOTWeen 2023-09-07 17:05:11 +09:00
hadashiA
9135c7ce56 Add check if UnityWebRequest was destroyed 2023-09-07 10:35:48 +09:00
hadashiA
7fae415689 Reduce the times of AwakeMonitor checking 2023-09-07 10:03:55 +09:00
hadashiA
e5cc8667ac docs: update TOC 2023-09-07 00:58:51 +00:00
hadashiA
0ea18d0e16 Update README about DOTween 2023-09-07 09:58:00 +09:00
hadashiA
2d674999f0 Use InnerException when only be one 2023-09-07 09:11:47 +09:00
David Klein
3121903fa3 Earlier intialization for Unitask, depending on unity version 2023-09-04 11:00:50 +02:00
hadashiA
af2e49aa29 Fix TriggerEvent.SetCancel 2023-09-03 20:40:04 +09:00
hadashiA
22940635fe Fix TriggerEvent problem with iterate breaking on Remove when it has multiple handlers 2023-09-02 22:26:09 +09:00
hadashiA
c1042b32b7 Merge pull request #488 from Cysharp/revert-445-fix-wait-async
Revert "Fixed https://github.com/Cysharp/UniTask/issues/444"
2023-09-01 20:08:55 +09:00
hadashiA
29a144694d Revert "Fixed https://github.com/Cysharp/UniTask/issues/444" 2023-09-01 19:52:22 +09:00
hadashiA
548d56e654 Merge pull request #445 from faveris/fix-wait-async
Fixed https://github.com/Cysharp/UniTask/issues/444
2023-09-01 17:06:31 +09:00
hadashiA
6fb4f2d6d2 Support exception unwrapping for AsUniTask of Task.WhenAll 2023-09-01 16:58:11 +09:00
hadashiA
8eac07ad24 Use innerException for Task.AsUniTask 2023-09-01 10:49:43 +09:00
hadashiA
716402a180 Fix a problem in dotween where an extra update would run after canceling 2023-08-31 19:22:17 +09:00
hadashiA
4c3d6938ed Merge pull request #484 from Cysharp/hadashiA/fix-async-enumerable
Fix problem with finally in UniTaskAsyncEnumerable.Create not being executed
2023-08-31 19:17:31 +09:00
hadashiA
b4486802f2 Fix problem with part of await foreach not executing on break 2023-08-31 12:42:53 +09:00
Yoshifumi Kawai
d210e3d76a Merge pull request #457 from sgaumin/wait-for-seconds
Add WaitForSeconds method declarations #371
2023-06-23 19:04:48 +09:00
Ikiru Yoshizaki
f2773f585e Revert "Revert "Merge pull request #459 from Cysharp/feature/prevent""
This reverts commit 305695ad5d.
2023-05-08 12:22:51 +09:00
Ikiru Yoshizaki
305695ad5d Revert "Merge pull request #459 from Cysharp/feature/prevent"
This reverts commit 356a4ee62e.
2023-04-26 14:14:51 +09:00
Ikiru Yoshizaki
418ab36a72 Merge pull request #460 from Cysharp/feature/unity
chore: change unity build to cysharp actions
2023-04-26 12:35:55 +09:00
Ikiru Yoshizaki
563b4fbbd5 chore: remove license 2023-04-25 19:48:54 +09:00
Ikiru Yoshizaki
878d33115f chore: change unity build to cysharp actions 2023-04-25 19:39:40 +09:00
Ikiru Yoshizaki
356a4ee62e Merge pull request #459 from Cysharp/feature/prevent
chote: prevent github workflow change
2023-04-25 18:50:19 +09:00
Ikiru Yoshizaki
eb32ae25e0 chote: prevent github workflow change 2023-04-25 16:56:50 +09:00
Sébastien Gaumin
3ca4062536 Add WaitForSeconds method declarations #371 2023-04-07 00:33:31 +09:00
Artem Kolesnykov
019f8aaf30 Deleted preserveRemoveSelf because Remove() should always remove a trigger for pooling to work correctly 2023-02-12 17:33:19 +02:00
Artem Kolesnykov
663fa737f3 Added a test case for https://github.com/Cysharp/UniTask/issues/444 2023-02-12 17:33:19 +02:00
Yoshifumi Kawai
73d86259ce f 2022-12-26 06:02:57 +09:00
Yoshifumi Kawai
c7eedf85c7 Merge pull request #421 from ivribalko/master
fixed typo in README.md (AysncLocal)
2022-11-21 12:48:07 +09:00
Ivan Rybalko
8dc3ffd552 fixed typo (AysncLocal) 2022-11-10 20:28:07 +00:00
github-actions[bot]
b992a061fb feat: Update package.json to 2.3.3 2022-11-01 11:41:05 +00:00
neuecc
4fc09a6f61 more 2022-11-01 20:40:24 +09:00
neuecc
e57176a43c Merge remote-tracking branch 'origin/master' 2022-11-01 20:39:37 +09:00
Yoshifumi Kawai
710d0d9012 Merge pull request #418 from adarapata/fix-asyncenumerable-cancel
Fix UnityEventHandlerAsyncEnumerator cancellation
2022-11-01 20:39:22 +09:00
neuecc
039de3ef65 Text -> UnityEngine.UI.Text #401 2022-11-01 20:33:24 +09:00
imo
de38f63a55 Token was incorrectly specified. 2022-11-01 20:12:55 +09:00
Yoshifumi Kawai
38f8193199 Update README.md 2022-10-25 13:51:57 +09:00
neuecc
15cffb7357 docs: update TOC 2022-10-25 04:50:13 +00:00
Yoshifumi Kawai
d55748e05b Merge pull request #374 from wqaetly/readme_cn
doc:provide simple chinese readme
2022-10-25 13:50:01 +09:00
NKG丶MadLife
5602861dd4 Update README_CN.md 2022-10-25 12:10:28 +08:00
github-actions[bot]
d2245bc38b feat: Update package.json to 2.3.2 2022-10-24 12:59:01 +00:00
neuecc
f092f6a112 Fix AwaitForAllAssets stackoverflow #394 2022-10-24 21:57:42 +09:00
neuecc
ed617a04a6 if UNITY_2022_2_OR_NEWER, use destroyCancellationToken 2022-10-24 21:56:03 +09:00
neuecc
340736795c UnityEvent.AsAsyncEnumerable handle cancel correctly #365 2022-10-24 21:51:23 +09:00
neuecc
dc804ffb13 breaking changes, UniTask.WaitForFixedUpdate wait at LastFixedUpdate #377 2022-10-24 21:18:36 +09:00
neuecc
a879989d1c Unity 2023.1.0a15, remove AsyncOperation.GetAwaiter to avoid conflict 2022-10-24 21:11:49 +09:00
Yoshifumi Kawai
ee54559532 Merge pull request #413 from battleroy/battleroy/observable-extension-cancellation-token-forwarding
Fix cancellation token forwarding
2022-10-12 10:53:30 +09:00
Evgeny Chasovitin
4a72ec2a1a Fix cancellation token forwarding at FirstValueToUniTaskObserver and ToUniTaskObserver; 2022-10-11 23:01:19 +04:00
Yoshifumi Kawai
e999268305 Merge pull request #395 from kroonhorstdino/diagnostics_helper_null_check
Diagnostics helper null check
2022-09-30 18:49:10 +09:00
Yoshifumi Kawai
8300c1b1e6 Merge pull request #399 from shiena/fix/prevent-nre
fix: prevent NullReferenceException in TimeoutController
2022-09-30 18:04:57 +09:00
KOGA Mitsuhiro
daa0c7b9a0 fix: prevent NullReferenceException in TimeoutController 2022-09-14 02:56:06 +09:00
KOGA Mitsuhiro
9b9a4ec76a fix: prevent NullReferenceException in TimeoutController 2022-09-08 15:12:05 +09:00
Christoph Hüter
3f8e43b83f Remove empty line with spaces 2022-08-31 03:00:22 +02:00
Christoph Hüter
cf6f0799e9 Remove spaces in empty line 2022-08-25 13:51:44 +02:00
Christoph Hüter
91ba4f003a Add null checks to diagnostics helper functions 2022-08-25 13:48:52 +02:00
Yoshifumi Kawai
f48cb4b03e Merge pull request #392 from Ryuu-64/master
Typo in TaskPool.cs annotation internaly -> internally
2022-08-23 10:38:44 +09:00
DESKTOP-FQ830JM\Ryuu
70a243d978 typo in TaskPool.cs internaly -> internally 2022-08-22 12:20:52 +08:00
Yoshifumi Kawai
9b95f3b9f6 Merge pull request #385 from fpagyu/support-addressablesCN
re-define UNITASK_ADDRESSABLE_SUPPORT for supporting Addressables.CN
2022-08-02 10:46:39 +09:00
yuzj
a25adb601b re-define UNITASK_ADDRESSABLE_SUPPORT for supporting Addressables.CN 2022-08-01 18:21:04 +08:00
Ikiru Yoshizaki
e6240879c4 chore: checkout@v3 2022-07-26 15:34:50 +09:00
Ikiru Yoshizaki
a94e8cceac Merge pull request #381 from Cysharp/feature/actions
feat: use Cysharp/Actions reusable workflows/actions
2022-07-26 13:59:46 +09:00
Ikiru Yoshizaki
0595a4182a feat: use Cysharp/Actions for release 2022-07-26 13:10:40 +09:00
Ikiru Yoshizaki
df96c119c1 chore: set timeout 2022-07-26 13:10:32 +09:00
Ikiru Yoshizaki
534f4a2588 chore: use Cysharp/Actions reusable workflow stale 2022-07-26 13:10:22 +09:00
Ikiru Yoshizaki
873485ad1a chore: IsPackable marking 2022-07-26 13:10:10 +09:00
NKG丶MadLife
f6037d6c9b doc:provide simple chinese readme 2022-07-16 10:02:16 +08:00
Yoshifumi Kawai
78db78c7bd Merge pull request #369 from nolimet/bugfix/issue#368
Fix for issue #368 UnityWebRequestException extra line in exception message
2022-06-23 17:46:29 +09:00
Jesse Stam
226e272787 Added simple check to see if there is text.
Add this so we don't add a new line we don't need.
2022-06-23 09:31:05 +02:00
neuecc
9e2163616b Merge remote-tracking branch 'origin/master' 2022-03-03 08:14:22 +09:00
neuecc
52df6fbf3f t 2022-03-03 08:14:18 +09:00
38 changed files with 2042 additions and 403 deletions

1
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1 @@
github: [neuecc]

View File

@@ -4,8 +4,6 @@ on:
push:
branches:
- "master"
tags:
- "!*" # not a tag push
pull_request:
branches:
- "master"
@@ -13,67 +11,60 @@ on:
jobs:
build-dotnet:
runs-on: ubuntu-latest
env:
DOTNET_CLI_TELEMETRY_OPTOUT: 1
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
NUGET_XMLDOC_MODE: skip
timeout-minutes: 10
steps:
- uses: actions/checkout@v2
- run: dotnet test -c Debug ./src/UniTask.NetCoreTests/UniTask.NetCoreTests.csproj
- uses: actions/checkout@v3
- uses: Cysharp/Actions/.github/actions/setup-dotnet@main
with:
dotnet-version: |
6.0.x
7.0.x
- run: dotnet build -c Debug
- run: dotnet test -c Debug
build-unity:
if: "((github.event_name == 'push' && github.repository_owner == 'Cysharp') || startsWith(github.event.pull_request.head.label, 'Cysharp:'))"
strategy:
matrix:
unity: ["2019.3.9f1", "2019.4.13f1", "2020.1.12f1"]
include:
- unity: 2019.3.9f1
license: UNITY_LICENSE_2019
- unity: 2019.4.13f1
license: UNITY_LICENSE_2019
- unity: 2020.1.12f1
license: UNITY_LICENSE_2020
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
# Execute scripts: RuntimeUnitTestToolkit
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod UnitTestBuilder.BuildUnitTest /headless /ScriptBackend mono /BuildTarget StandaloneLinux64
- name: Build UnitTest(Linux64, mono)
uses: game-ci/unity-builder@v2.0-alpha-6
uses: Cysharp/Actions/.github/actions/unity-builder@main
env:
UNITY_LICENSE: ${{ secrets[matrix.license] }}
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
with:
projectPath: src/UniTask
unityVersion: ${{ matrix.unity }}
targetPlatform: StandaloneLinux64
buildMethod: UnitTestBuilder.BuildUnitTest
customParameters: /headless /ScriptBackend mono
versioning: None
- name: Execute UnitTest
run: ./src/UniTask/bin/UnitTest/StandaloneLinux64_Mono2x/test
# Execute scripts: Export Package
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
- name: Export unitypackage
uses: game-ci/unity-builder@v2.0-alpha-6
- name: Build Unity (.unitypacakge)
uses: Cysharp/Actions/.github/actions/unity-builder@main
env:
UNITY_LICENSE: ${{ secrets[matrix.license] }}
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
with:
projectPath: src/UniTask
unityVersion: ${{ matrix.unity }}
targetPlatform: StandaloneLinux64
buildMethod: PackageExporter.Export
versioning: None
- name: check all .meta is commited
run: |
if git ls-files --others --exclude-standard -t | grep --regexp='[.]meta$'; then
echo "Detected .meta file generated. Do you forgot commit a .meta file?"
exit 1
else
echo "Great, all .meta files are commited."
fi
working-directory: src/UniTask
- uses: Cysharp/Actions/.github/actions/check-metas@main # check meta files
with:
directory: src/UniTask
# Store artifacts.
- uses: actions/upload-artifact@v2

View File

@@ -9,9 +9,10 @@ on:
jobs:
run-docfx:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: actions/checkout@v3
with:
repository: Cysharp/DocfxTemplate
path: docs/_DocfxTemplate

View File

@@ -6,90 +6,44 @@ on:
tag:
description: "tag: git tag you want create. (sample 1.0.0)"
required: true
dry_run:
description: "dry_run: true will never create relase/nuget."
dry-run:
description: "dry-run: true will never create relase/nuget."
required: true
default: "false"
default: false
type: boolean
env:
GIT_TAG: ${{ github.event.inputs.tag }}
DRY_RUN: ${{ github.event.inputs.dry_run }}
DRY_RUN_BRANCH_PREFIX: "test_release"
DRY_RUN: ${{ github.event.inputs.dry-run }}
jobs:
update-packagejson:
runs-on: ubuntu-latest
env:
TARGET_FILE: ./src/UniTask/Assets/Plugins/UniTask/package.json
outputs:
sha: ${{ steps.commit.outputs.sha }}
steps:
- uses: actions/checkout@v2
- name: Output package.json (Before)
run: cat ${{ env.TARGET_FILE}}
- name: Update package.json to version ${{ env.GIT_TAG }}
run: sed -i -e "s/\(\"version\":\) \"\(.*\)\",/\1 \"${{ env.GIT_TAG }}\",/" ${{ env.TARGET_FILE }}
- name: Check update
id: check_update
run: |
cat ${{ env.TARGET_FILE}}
git diff --exit-code || echo "::set-output name=changed::1"
- name: Commit files
id: commit
if: steps.check_update.outputs.changed == '1'
run: |
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git commit -m "feat: Update package.json to ${{ env.GIT_TAG }}" -a
echo "::set-output name=sha::$(git rev-parse HEAD)"
- name: Check sha
run: echo "SHA ${SHA}"
env:
SHA: ${{ steps.commit.outputs.sha }}
- name: Create Tag
if: steps.check_update.outputs.changed == '1'
run: git tag ${{ env.GIT_TAG }}
- name: Push changes
if: env.DRY_RUN == 'false' && steps.check_update.outputs.changed == '1'
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ github.ref }}
tags: true
- name: Push changes (dry_run)
if: env.DRY_RUN == 'true' && steps.check_update.outputs.changed == '1'
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ env.DRY_RUN_BRANCH_PREFIX }}-${{ env.GIT_TAG }}
tags: false
uses: Cysharp/Actions/.github/workflows/update-packagejson.yaml@main
with:
file-path: ./src/UniTask/Assets/Plugins/UniTask/package.json
tag: ${{ github.event.inputs.tag }}
dry-run: ${{ fromJson(github.event.inputs.dry-run) }}
build-dotnet:
needs: [update-packagejson]
runs-on: ubuntu-latest
timeout-minutes: 10
env:
DOTNET_CLI_TELEMETRY_OPTOUT: 1
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
NUGET_XMLDOC_MODE: skip
steps:
- run: echo ${{ needs.update-packagejson.outputs.sha }}
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
ref: ${{ needs.update-packagejson.outputs.sha }}
- uses: Cysharp/Actions/.github/actions/setup-dotnet@main
with:
dotnet-version: |
3.1.x
6.0.x
# build and pack
- run: dotnet build -c Release -p:Version=${{ env.GIT_TAG }}
- run: dotnet test -c Release --no-build
- run: dotnet pack ./src/UniTask.NetCore/UniTask.NetCore.csproj -c Release --no-build -p:Version=${{ env.GIT_TAG }} -o ./publish
# Store artifacts.
- uses: actions/upload-artifact@v1
- uses: actions/upload-artifact@v2
with:
name: nuget
path: ./publish/
@@ -99,38 +53,30 @@ jobs:
strategy:
matrix:
unity: ["2019.3.9f1"]
include:
- unity: 2019.3.9f1
license: UNITY_LICENSE_2019
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- run: echo ${{ needs.update-packagejson.outputs.sha }}
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
ref: ${{ needs.update-packagejson.outputs.sha }}
# Execute scripts: Export Package
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
- name: Export unitypackage
uses: game-ci/unity-builder@v2.0-alpha-6
- name: Build Unity (.unitypacakge)
uses: Cysharp/Actions/.github/actions/unity-builder@main
env:
UNITY_LICENSE: ${{ secrets[matrix.license] }}
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
with:
projectPath: src/UniTask
unityVersion: ${{ matrix.unity }}
targetPlatform: StandaloneLinux64
buildMethod: PackageExporter.Export
versioning: None
- name: check all .meta is commited
run: |
if git ls-files --others --exclude-standard -t | grep --regexp='[.]meta$'; then
echo "Detected .meta file generated. Do you forgot commit a .meta file?"
exit 1
else
echo "Great, all .meta files are commited."
fi
working-directory: src/UniTask
- uses: Cysharp/Actions/.github/actions/check-metas@main # check meta files
with:
directory: src/UniTask
# Store artifacts.
- uses: actions/upload-artifact@v2
@@ -139,14 +85,12 @@ jobs:
path: ./src/UniTask/UniTask.${{ env.GIT_TAG }}.unitypackage
create-release:
if: github.event.inputs.dry_run == 'false'
if: github.event.inputs.dry-run == 'false'
needs: [update-packagejson, build-dotnet, build-unity]
runs-on: ubuntu-latest
env:
DOTNET_CLI_TELEMETRY_OPTOUT: 1
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
NUGET_XMLDOC_MODE: skip
timeout-minutes: 10
steps:
- uses: Cysharp/Actions/.github/actions/setup-dotnet@main
# Create Releases
- uses: actions/create-release@v1
id: create_release
@@ -173,12 +117,8 @@ jobs:
asset_content_type: application/octet-stream
cleanup:
if: github.event.inputs.dry_run == 'true'
needs: [build-dotnet, build-unity]
runs-on: ubuntu-latest
steps:
- name: Delete branch
uses: dawidd6/action-delete-branch@v3
with:
github_token: ${{ github.token }}
branches: ${{ env.DRY_RUN_BRANCH_PREFIX }}-${{ env.GIT_TAG }}
if: needs.update-packagejson.outputs.is-branch-created == 'true'
needs: [update-packagejson, build-dotnet, build-unity]
uses: Cysharp/Actions/.github/workflows/clean-packagejson-branch.yaml@main
with:
branch: ${{ needs.update-packagejson.outputs.branch-name }}

View File

@@ -0,0 +1,10 @@
name: Prevent github change
on:
pull_request:
paths:
- ".github/**/*.yaml"
- ".github/**/*.yml"
jobs:
detect:
uses: Cysharp/Actions/.github/workflows/prevent-github-change.yaml@main

View File

@@ -1,24 +1,10 @@
name: "Close stale issues"
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * *"
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
# enable issue
stale-issue-message: "This issue is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 7 days."
stale-issue-label: "stale"
# enable pr
stale-pr-message: "This PR is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 7 days."
stale-pr-label: "stale"
days-before-stale: 90
days-before-close: 7
exempt-issue-labels: "wip"
exempt-pr-labels: "wip"
remove-stale-when-updated: true
uses: Cysharp/Actions/.github/workflows/stale-issue.yaml@main

View File

@@ -1,6 +1,6 @@
UniTask
===
[![GitHub Actions](https://github.com/Cysharp/UniTask/workflows/Build-Debug/badge.svg)](https://github.com/Cysharp/UniTask/actions) [![Releases](https://img.shields.io/github/release/Cysharp/UniTask.svg)](https://github.com/Cysharp/UniTask/releases)
[![GitHub Actions](https://github.com/Cysharp/UniTask/workflows/Build-Debug/badge.svg)](https://github.com/Cysharp/UniTask/actions) [![Releases](https://img.shields.io/github/release/Cysharp/UniTask.svg)](https://github.com/Cysharp/UniTask/releases) [![Readme_CN](https://img.shields.io/badge/UniTask-%E4%B8%AD%E6%96%87%E6%96%87%E6%A1%A3-red)](https://github.com/Cysharp/UniTask/blob/master/README_CN.md)
Provides an efficient allocation free async/await integration for Unity.
@@ -44,7 +44,6 @@ For advanced tips, see blog post: [Extends UnityWebRequest via async decorator p
- [API References](#api-references)
- [UPM Package](#upm-package)
- [Install via git URL](#install-via-git-url)
- [Install via OpenUPM](#install-via-openupm)
- [.NET Core](#net-core)
- [License](#license)
@@ -86,8 +85,13 @@ async UniTask<string> DemoAsync()
await UniTask.Yield();
await UniTask.NextFrame();
// replacement of WaitForEndOfFrame(requires MonoBehaviour(CoroutineRunner))
// replacement of WaitForEndOfFrame
#if UNITY_2023_1_OR_NEWER
await UniTask.WaitForEndOfFrame();
#else
// requires MonoBehaviour(CoroutineRunner))
await UniTask.WaitForEndOfFrame(this); // this is MonoBehaviour
#endif
// replacement of yield return new WaitForFixedUpdate(same as UniTask.Yield(PlayerLoopTiming.FixedUpdate))
await UniTask.WaitForFixedUpdate();
@@ -499,6 +503,8 @@ It indicates when to run, you can check [PlayerLoopList.md](https://gist.github.
`PlayerLoopTiming.Update` is similar to `yield return null` in a coroutine, but it is called before Update(Update and uGUI events(button.onClick, etc...) are called on `ScriptRunBehaviourUpdate`, yield return null is called on `ScriptRunDelayedDynamicFrameRate`). `PlayerLoopTiming.FixedUpdate` is similar to `WaitForFixedUpdate`.
> `PlayerLoopTiming.LastPostLateUpdate` is not equivalent to coroutine's `yield return new WaitForEndOfFrame()`. Coroutine's WaitForEndOfFrame seems to run after the PlayerLoop is done. Some methods that require coroutine's end of frame(`Texture2D.ReadPixels`, `ScreenCapture.CaptureScreenshotAsTexture`, `CommandBuffer`, etc) do not work correctly when replaced with async/await. In these cases, pass MonoBehaviour(coroutine runnner) to `UniTask.WaitForEndOfFrame`. For example, `await UniTask.WaitForEndOfFrame(this);` is lightweight allocation free alternative of `yield return new WaitForEndOfFrame()`.
>
> Note: In Unity 2023.1 or newer, `await UniTask.WaitForEndOfFrame();` no longer requires MonoBehaviour. It uses `UnityEngine.Awaitable.EndOfFrameAsync`.
`yield return null` and `UniTask.Yield` are similar but different. `yield return null` always returns next frame but `UniTask.Yield` returns next called. That is, call `UniTask.Yield(PlayerLoopTiming.Update)` on `PreUpdate`, it returns same frame. `UniTask.NextFrame()` guarantees return next frame, you can expect this to behave exactly the same as `yield return null`.
@@ -658,7 +664,8 @@ By default, UniTask supports TextMeshPro(`BindTo(TMP_Text)` and `TMP_InputField`
There are defined in separated asmdefs like `UniTask.TextMeshPro`, `UniTask.DOTween`, `UniTask.Addressables`.
TextMeshPro and Addressables support are automatically enabled when importing their packages from package manager. However for DOTween support, it is required to import `com.demigiant.dotween` from [OpenUPM](https://openupm.com/packages/com.demigiant.dotween/) or to define `UNITASK_DOTWEEN_SUPPORT` to enable it.
TextMeshPro and Addressables support are automatically enabled when importing their packages from package manager.
However for DOTween support, after importing from the [DOTWeen assets](https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676r) and define the scripting define symbol `UNITASK_DOTWEEN_SUPPORT` to enable it.
```csharp
// sequential
@@ -717,7 +724,7 @@ Async LINQ is enabled when `using Cysharp.Threading.Tasks.Linq;`, and `UniTaskAs
It's closer to UniRx (Reactive Extensions), but UniTaskAsyncEnumerable is a pull-based asynchronous stream, whereas Rx was a push-based asynchronous stream. Note that although similar, the characteristics are different and the details behave differently along with them.
`UniTaskAsyncEnumerable` is the entry point like `Enumerable`. In addition to the standard query operators, there are other generators for Unity such as `EveryUpdate`, `Timer`, `TimerFrame`, `Interval`, `IntervalFrame`, and `EveryValueChanged`. And also added additional UniTask original query operators like `Append`, `Prepend`, `DistinctUntilChanged`, `ToHashSet`, `Buffer`, `CombineLatest`, `Do`, `Never`, `ForEachAsync`, `Pairwise`, `Publish`, `Queue`, `Return`, `SkipUntil`, `TakeUntil`, `SkipUntilCanceled`, `TakeUntilCanceled`, `TakeLast`, `Subscribe`.
`UniTaskAsyncEnumerable` is the entry point like `Enumerable`. In addition to the standard query operators, there are other generators for Unity such as `EveryUpdate`, `Timer`, `TimerFrame`, `Interval`, `IntervalFrame`, and `EveryValueChanged`. And also added additional UniTask original query operators like `Append`, `Prepend`, `DistinctUntilChanged`, `ToHashSet`, `Buffer`, `CombineLatest`,`Merge` `Do`, `Never`, `ForEachAsync`, `Pairwise`, `Publish`, `Queue`, `Return`, `SkipUntil`, `TakeUntil`, `SkipUntilCanceled`, `TakeUntilCanceled`, `TakeLast`, `Subscribe`.
The method with Func as an argument has three additional overloads, `***Await`, `***AwaitWithCancellation`.
@@ -1072,13 +1079,6 @@ or add `"com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/
If you want to set a target version, UniTask uses the `*.*.*` release tag so you can specify a version like `#2.1.0`. For example `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.1.0`.
### Install via OpenUPM
The package is available on the [openupm registry](https://openupm.com). It's recommended to install it via [openupm-cli](https://github.com/openupm/openupm-cli).
```
openupm add com.cysharp.unitask
```
.NET Core
---
@@ -1088,7 +1088,7 @@ For .NET Core, use NuGet.
UniTask of .NET Core version is a subset of Unity UniTask with PlayerLoop dependent methods removed.
It runs at higher performance than the standard Task/ValueTask, but you should be careful to ignore the ExecutionContext/SynchronizationContext when using it. `AysncLocal` also does not work because it ignores ExecutionContext.
It runs at higher performance than the standard Task/ValueTask, but you should be careful to ignore the ExecutionContext/SynchronizationContext when using it. `AsyncLocal` also does not work because it ignores ExecutionContext.
If you use UniTask internally, but provide ValueTask as an external API, you can write it like the following(Inspired by [PooledAwait](https://github.com/mgravell/PooledAwait)).

1134
README_CN.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp3.1;netstandard2.1;netstandard2.0</TargetFrameworks>
<TargetFrameworks>net6.0;net7.0;netstandard2.1;netstandard2.0</TargetFrameworks>
<AssemblyName>UniTask</AssemblyName>
<LangVersion>8.0</LangVersion>
<RootNamespace>Cysharp.Threading.Tasks</RootNamespace>
@@ -23,6 +23,7 @@
<PackageIcon>Icon.png</PackageIcon>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>opensource.snk</AssemblyOriginatorKeyFile>
<IsPackable>true</IsPackable>
</PropertyGroup>
<ItemGroup>

View File

@@ -2,8 +2,9 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace>NetCoreSandbox</RootNamespace>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>

View File

@@ -159,6 +159,30 @@ namespace NetCoreTests.Linq
list.Should().Equal(100, 200, 300, 400);
}
[Fact]
public async Task AwaitForeachBreak()
{
var finallyCalled = false;
var enumerable = UniTaskAsyncEnumerable.Create<int>(async (writer, _) =>
{
try
{
await writer.YieldAsync(1);
}
finally
{
finallyCalled = true;
}
});
await foreach (var x in enumerable)
{
x.Should().Be(1);
break;
}
finallyCalled.Should().BeTrue();
}
async IAsyncEnumerable<int> Range(int from, int count)
{
for (int i = 0; i < count; i++)

View File

@@ -0,0 +1,137 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using Cysharp.Threading.Tasks.Linq;
using FluentAssertions;
using Xunit;
namespace NetCoreTests.Linq
{
public class MergeTest
{
[Fact]
public async Task TwoSource()
{
var semaphore = new SemaphoreSlim(1, 1);
var a = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
{
await UniTask.SwitchToThreadPool();
await semaphore.WaitAsync();
await writer.YieldAsync("A1");
semaphore.Release();
await semaphore.WaitAsync();
await writer.YieldAsync("A2");
semaphore.Release();
});
var b = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
{
await UniTask.SwitchToThreadPool();
await semaphore.WaitAsync();
await writer.YieldAsync("B1");
await writer.YieldAsync("B2");
semaphore.Release();
await semaphore.WaitAsync();
await writer.YieldAsync("B3");
semaphore.Release();
});
var result = await a.Merge(b).ToArrayAsync();
result.Should().Equal("A1", "B1", "B2", "A2", "B3");
}
[Fact]
public async Task ThreeSource()
{
var semaphore = new SemaphoreSlim(0, 1);
var a = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
{
await UniTask.SwitchToThreadPool();
await semaphore.WaitAsync();
await writer.YieldAsync("A1");
semaphore.Release();
await semaphore.WaitAsync();
await writer.YieldAsync("A2");
semaphore.Release();
});
var b = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
{
await UniTask.SwitchToThreadPool();
await semaphore.WaitAsync();
await writer.YieldAsync("B1");
await writer.YieldAsync("B2");
semaphore.Release();
await semaphore.WaitAsync();
await writer.YieldAsync("B3");
semaphore.Release();
});
var c = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
{
await UniTask.SwitchToThreadPool();
await writer.YieldAsync("C1");
semaphore.Release();
});
var result = await a.Merge(b, c).ToArrayAsync();
result.Should().Equal("C1", "A1", "B1", "B2", "A2", "B3");
}
[Fact]
public async Task Throw()
{
var a = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
{
await writer.YieldAsync("A1");
});
var b = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
{
throw new UniTaskTestException();
});
var enumerator = a.Merge(b).GetAsyncEnumerator();
(await enumerator.MoveNextAsync()).Should().Be(true);
enumerator.Current.Should().Be("A1");
await Assert.ThrowsAsync<UniTaskTestException>(async () => await enumerator.MoveNextAsync());
}
[Fact]
public async Task Cancel()
{
var cts = new CancellationTokenSource();
var a = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
{
await writer.YieldAsync("A1");
});
var b = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
{
await writer.YieldAsync("B1");
});
var enumerator = a.Merge(b).GetAsyncEnumerator(cts.Token);
(await enumerator.MoveNextAsync()).Should().Be(true);
enumerator.Current.Should().Be("A1");
cts.Cancel();
await Assert.ThrowsAsync<OperationCanceledException>(async () => await enumerator.MoveNextAsync());
}
}
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using Xunit;
namespace NetCoreTests
{
public class TaskExtensionsTest
{
[Fact]
public async Task PropagateException()
{
await Assert.ThrowsAsync<InvalidOperationException>(async () =>
{
await ThrowAsync().AsUniTask();
});
await Assert.ThrowsAsync<InvalidOperationException>(async () =>
{
await ThrowOrValueAsync().AsUniTask();
});
}
[Fact]
public async Task PropagateExceptionWhenAll()
{
await Assert.ThrowsAsync<InvalidOperationException>(async () =>
{
await Task.WhenAll(ThrowAsync(), ThrowAsync()).AsUniTask();
});
}
async Task ThrowAsync()
{
throw new InvalidOperationException();
}
async Task<int> ThrowOrValueAsync()
{
throw new InvalidOperationException();
}
}
}

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<IsPackable>false</IsPackable>

View File

@@ -0,0 +1,80 @@
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using FluentAssertions;
using NetCoreTests.Linq;
using Xunit;
namespace NetCoreTests
{
public class AutoResetUniTaskCompletionSourceTest
{
[Fact]
public async Task SetResultAfterReturn()
{
var source1 = AutoResetUniTaskCompletionSource.Create();
source1.TrySetResult();
await source1.Task;
source1.TrySetResult().Should().BeFalse();
var source2 = AutoResetUniTaskCompletionSource.Create();
source2.TrySetResult();
await source2.Task;
source2.TrySetResult().Should().BeFalse();
}
[Fact]
public async Task SetCancelAfterReturn()
{
var source = AutoResetUniTaskCompletionSource.Create();
source.TrySetResult();
await source.Task;
source.TrySetCanceled().Should().BeFalse();
}
[Fact]
public async Task SetExceptionAfterReturn()
{
var source = AutoResetUniTaskCompletionSource.Create();
source.TrySetResult();
await source.Task;
source.TrySetException(new UniTaskTestException()).Should().BeFalse();
}
[Fact]
public async Task SetResultWithValueAfterReturn()
{
var source1 = AutoResetUniTaskCompletionSource<int>.Create();
source1.TrySetResult(100);
(await source1.Task).Should().Be(100);
source1.TrySetResult(100).Should().BeFalse();
var source2 = AutoResetUniTaskCompletionSource.Create();
source2.TrySetResult();
await source2.Task;
source2.TrySetResult().Should().BeFalse();
}
[Fact]
public async Task SetCancelWithValueAfterReturn()
{
var source = AutoResetUniTaskCompletionSource<int>.Create();
source.TrySetResult(100);
(await source.Task).Should().Be(100);
source.TrySetCanceled().Should().BeFalse();
}
[Fact]
public async Task SetExceptionWithValueAfterReturn()
{
var source = AutoResetUniTaskCompletionSource<int>.Create();
source.TrySetResult(100);
(await source.Task).Should().Be(100);
source.TrySetException(new UniTaskTestException()).Should().BeFalse();
}
}
}

View File

@@ -16,7 +16,12 @@
"name": "com.unity.addressables",
"expression": "",
"define": "UNITASK_ADDRESSABLE_SUPPORT"
},
{
"name": "com.unity.addressables.cn",
"expression": "",
"define": "UNITASK_ADDRESSABLE_SUPPORT"
}
],
"noEngineReferences": false
}
}

View File

@@ -144,22 +144,20 @@ namespace Cysharp.Threading.Tasks
}
readonly TweenCallback onCompleteCallbackDelegate;
readonly TweenCallback onUpdateDelegate;
Tween tween;
TweenCancelBehaviour cancelBehaviour;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationRegistration;
CallbackType callbackType;
bool canceled;
TweenCallback originalUpdateAction;
TweenCallback originalCompleteAction;
UniTaskCompletionSourceCore<AsyncUnit> core;
TweenConfiguredSource()
{
onCompleteCallbackDelegate = OnCompleteCallbackDelegate;
onUpdateDelegate = OnUpdate;
}
public static IUniTaskSource Create(Tween tween, TweenCancelBehaviour cancelBehaviour, CancellationToken cancellationToken, CallbackType callbackType, out short token)
@@ -179,17 +177,8 @@ namespace Cysharp.Threading.Tasks
result.cancelBehaviour = cancelBehaviour;
result.cancellationToken = cancellationToken;
result.callbackType = callbackType;
result.originalUpdateAction = tween.onUpdate;
result.canceled = false;
if (result.originalUpdateAction == result.onUpdateDelegate)
{
result.originalUpdateAction = null;
}
tween.onUpdate = result.onUpdateDelegate;
switch (callbackType)
{
case CallbackType.Kill:
@@ -225,6 +214,50 @@ namespace Cysharp.Threading.Tasks
result.originalCompleteAction = null;
}
if (cancellationToken.CanBeCanceled)
{
result.cancellationRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(x =>
{
var source = (TweenConfiguredSource)x;
switch (source.cancelBehaviour)
{
case TweenCancelBehaviour.Kill:
default:
source.tween.Kill(false);
break;
case TweenCancelBehaviour.KillAndCancelAwait:
source.canceled = true;
source.tween.Kill(false);
break;
case TweenCancelBehaviour.KillWithCompleteCallback:
source.tween.Kill(true);
break;
case TweenCancelBehaviour.KillWithCompleteCallbackAndCancelAwait:
source.canceled = true;
source.tween.Kill(true);
break;
case TweenCancelBehaviour.Complete:
source.tween.Complete(false);
break;
case TweenCancelBehaviour.CompleteAndCancelAwait:
source.canceled = true;
source.tween.Complete(false);
break;
case TweenCancelBehaviour.CompleteWithSequenceCallback:
source.tween.Complete(true);
break;
case TweenCancelBehaviour.CompleteWithSequenceCallbackAndCancelAwait:
source.canceled = true;
source.tween.Complete(true);
break;
case TweenCancelBehaviour.CancelAwait:
source.RestoreOriginalCallback();
source.core.TrySetCanceled(source.cancellationToken);
break;
}
}, result);
}
TaskTracker.TrackActiveTask(result, 3);
token = result.core.Version;
@@ -255,77 +288,6 @@ namespace Cysharp.Threading.Tasks
}
}
void OnUpdate()
{
originalUpdateAction?.Invoke();
if (!cancellationToken.IsCancellationRequested)
{
return;
}
switch (this.cancelBehaviour)
{
case TweenCancelBehaviour.Kill:
default:
this.tween.Kill(false);
break;
case TweenCancelBehaviour.KillAndCancelAwait:
this.canceled = true;
this.tween.Kill(false);
break;
case TweenCancelBehaviour.KillWithCompleteCallback:
this.tween.Kill(true);
break;
case TweenCancelBehaviour.KillWithCompleteCallbackAndCancelAwait:
this.canceled = true;
this.tween.Kill(true);
break;
case TweenCancelBehaviour.Complete:
this.tween.Complete(false);
break;
case TweenCancelBehaviour.CompleteAndCancelAwait:
this.canceled = true;
this.tween.Complete(false);
break;
case TweenCancelBehaviour.CompleteWithSequenceCallback:
this.tween.Complete(true);
break;
case TweenCancelBehaviour.CompleteWithSequenceCallbackAndCancelAwait:
this.canceled = true;
this.tween.Complete(true);
break;
case TweenCancelBehaviour.CancelAwait:
// restore to original callback
switch (callbackType)
{
case CallbackType.Kill:
tween.onKill = originalCompleteAction;
break;
case CallbackType.Complete:
tween.onComplete = originalCompleteAction;
break;
case CallbackType.Pause:
tween.onPause = originalCompleteAction;
break;
case CallbackType.Play:
tween.onPlay = originalCompleteAction;
break;
case CallbackType.Rewind:
tween.onRewind = originalCompleteAction;
break;
case CallbackType.StepComplete:
tween.onStepComplete = originalCompleteAction;
break;
default:
break;
}
this.core.TrySetCanceled(this.cancellationToken);
break;
}
}
static void DoCancelBeforeCreate(Tween tween, TweenCancelBehaviour tweenCancelBehaviour)
{
@@ -392,8 +354,18 @@ namespace Cysharp.Threading.Tasks
{
TaskTracker.RemoveTracking(this);
core.Reset();
tween.onUpdate = originalUpdateAction;
cancellationRegistration.Dispose();
RestoreOriginalCallback();
tween = default;
cancellationToken = default;
originalCompleteAction = default;
return pool.TryPush(this);
}
void RestoreOriginalCallback()
{
switch (callbackType)
{
case CallbackType.Kill:
@@ -417,12 +389,6 @@ namespace Cysharp.Threading.Tasks
default:
break;
}
tween = default;
cancellationToken = default;
originalUpdateAction = default;
originalCompleteAction = default;
return pool.TryPush(this);
}
}
}

View File

@@ -39,7 +39,7 @@ namespace Cysharp.Threading.Tasks.Internal
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowArgumentException<T>(string message)
public static void ThrowArgumentException(string message)
{
throw new ArgumentException(message);
}

View File

@@ -52,6 +52,7 @@ namespace Cysharp.Threading.Tasks.Linq
public UniTask DisposeAsync()
{
TaskTracker.RemoveTracking(this);
writer.Dispose();
return default;
}
@@ -127,7 +128,7 @@ namespace Cysharp.Threading.Tasks.Linq
}
}
sealed class AsyncWriter : IUniTaskSource, IAsyncWriter<T>
sealed class AsyncWriter : IUniTaskSource, IAsyncWriter<T>, IDisposable
{
readonly _Create enumerator;
@@ -137,6 +138,15 @@ namespace Cysharp.Threading.Tasks.Linq
{
this.enumerator = enumerator;
}
public void Dispose()
{
var status = core.GetStatus(core.Version);
if (status == UniTaskStatus.Pending)
{
core.TrySetCanceled();
}
}
public void GetResult(short token)
{

View File

@@ -0,0 +1,232 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Cysharp.Threading.Tasks.Internal;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<T> Merge<T>(this IUniTaskAsyncEnumerable<T> first, IUniTaskAsyncEnumerable<T> second)
{
Error.ThrowArgumentNullException(first, nameof(first));
Error.ThrowArgumentNullException(second, nameof(second));
return new Merge<T>(new [] { first, second });
}
public static IUniTaskAsyncEnumerable<T> Merge<T>(this IUniTaskAsyncEnumerable<T> first, IUniTaskAsyncEnumerable<T> second, IUniTaskAsyncEnumerable<T> third)
{
Error.ThrowArgumentNullException(first, nameof(first));
Error.ThrowArgumentNullException(second, nameof(second));
Error.ThrowArgumentNullException(third, nameof(third));
return new Merge<T>(new[] { first, second, third });
}
public static IUniTaskAsyncEnumerable<T> Merge<T>(this IEnumerable<IUniTaskAsyncEnumerable<T>> sources)
{
return new Merge<T>(sources.ToArray());
}
public static IUniTaskAsyncEnumerable<T> Merge<T>(params IUniTaskAsyncEnumerable<T>[] sources)
{
return new Merge<T>(sources);
}
}
internal sealed class Merge<T> : IUniTaskAsyncEnumerable<T>
{
readonly IUniTaskAsyncEnumerable<T>[] sources;
public Merge(IUniTaskAsyncEnumerable<T>[] sources)
{
if (sources.Length <= 0)
{
Error.ThrowArgumentException("No source async enumerable to merge");
}
this.sources = sources;
}
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
=> new _Merge(sources, cancellationToken);
enum MergeSourceState
{
Pending,
Running,
Completed,
}
sealed class _Merge : MoveNextSource, IUniTaskAsyncEnumerator<T>
{
static readonly Action<object> GetResultAtAction = GetResultAt;
readonly int length;
readonly IUniTaskAsyncEnumerator<T>[] enumerators;
readonly MergeSourceState[] states;
readonly Queue<(T, Exception, bool)> queuedResult = new Queue<(T, Exception, bool)>();
readonly CancellationToken cancellationToken;
int moveNextCompleted;
public T Current { get; private set; }
public _Merge(IUniTaskAsyncEnumerable<T>[] sources, CancellationToken cancellationToken)
{
this.cancellationToken = cancellationToken;
length = sources.Length;
states = ArrayPool<MergeSourceState>.Shared.Rent(length);
enumerators = ArrayPool<IUniTaskAsyncEnumerator<T>>.Shared.Rent(length);
for (var i = 0; i < length; i++)
{
enumerators[i] = sources[i].GetAsyncEnumerator(cancellationToken);
states[i] = (int)MergeSourceState.Pending;;
}
}
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
completionSource.Reset();
Interlocked.Exchange(ref moveNextCompleted, 0);
if (HasQueuedResult() && Interlocked.CompareExchange(ref moveNextCompleted, 1, 0) == 0)
{
(T, Exception, bool) value;
lock (states)
{
value = queuedResult.Dequeue();
}
var resultValue = value.Item1;
var exception = value.Item2;
var hasNext = value.Item3;
if (exception != null)
{
completionSource.TrySetException(exception);
}
else
{
Current = resultValue;
completionSource.TrySetResult(hasNext);
}
return new UniTask<bool>(this, completionSource.Version);
}
for (var i = 0; i < length; i++)
{
lock (states)
{
if (states[i] == MergeSourceState.Pending)
{
states[i] = MergeSourceState.Running;
}
else
{
continue;
}
}
var awaiter = enumerators[i].MoveNextAsync().GetAwaiter();
if (awaiter.IsCompleted)
{
GetResultAt(i, awaiter);
}
else
{
awaiter.SourceOnCompleted(GetResultAtAction, StateTuple.Create(this, i, awaiter));
}
}
return new UniTask<bool>(this, completionSource.Version);
}
public async UniTask DisposeAsync()
{
for (var i = 0; i < length; i++)
{
await enumerators[i].DisposeAsync();
}
ArrayPool<MergeSourceState>.Shared.Return(states, true);
ArrayPool<IUniTaskAsyncEnumerator<T>>.Shared.Return(enumerators, true);
}
static void GetResultAt(object state)
{
using (var tuple = (StateTuple<_Merge, int, UniTask<bool>.Awaiter>)state)
{
tuple.Item1.GetResultAt(tuple.Item2, tuple.Item3);
}
}
void GetResultAt(int index, UniTask<bool>.Awaiter awaiter)
{
bool hasNext;
bool completedAll;
try
{
hasNext = awaiter.GetResult();
}
catch (Exception ex)
{
if (Interlocked.CompareExchange(ref moveNextCompleted, 1, 0) == 0)
{
completionSource.TrySetException(ex);
}
else
{
lock (states)
{
queuedResult.Enqueue((default, ex, default));
}
}
return;
}
lock (states)
{
states[index] = hasNext ? MergeSourceState.Pending : MergeSourceState.Completed;
completedAll = !hasNext && IsCompletedAll();
}
if (hasNext || completedAll)
{
if (Interlocked.CompareExchange(ref moveNextCompleted, 1, 0) == 0)
{
Current = enumerators[index].Current;
completionSource.TrySetResult(!completedAll);
}
else
{
lock (states)
{
queuedResult.Enqueue((enumerators[index].Current, null, !completedAll));
}
}
}
}
bool HasQueuedResult()
{
lock (states)
{
return queuedResult.Count > 0;
}
}
bool IsCompletedAll()
{
lock (states)
{
for (var i = 0; i < length; i++)
{
if (states[i] != MergeSourceState.Completed)
{
return false;
}
}
}
return true;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ca56812f160c45d0bacb4339819edf1a
timeCreated: 1694133666

View File

@@ -285,7 +285,11 @@ namespace Cysharp.Threading.Tasks
return dest.ToArray();
}
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
#if UNITY_2020_1_OR_NEWER
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
#else
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
#endif
static void Init()
{
// capture default(unity) sync-context.
@@ -524,6 +528,14 @@ namespace Cysharp.Threading.Tasks
{
sb.AppendFormat("------{0}------", header.type.Name);
sb.AppendLine();
if (header.subSystemList is null)
{
sb.AppendFormat("{0} has no subsystems!", header.ToString());
sb.AppendLine();
continue;
}
foreach (var subSystem in header.subSystemList)
{
sb.AppendFormat("{0}", subSystem.type.Name);
@@ -545,6 +557,11 @@ namespace Cysharp.Threading.Tasks
foreach (var header in playerLoop.subSystemList)
{
if (header.subSystemList is null)
{
continue;
}
foreach (var subSystem in header.subSystemList)
{
if (subSystem.type == typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization))

View File

@@ -7,7 +7,7 @@ using System.Threading;
namespace Cysharp.Threading.Tasks
{
// internaly used but public, allow to user create custom operator with pooling.
// internally used but public, allow to user create custom operator with pooling.
public static class TaskPool
{

View File

@@ -99,7 +99,7 @@ namespace Cysharp.Threading.Tasks
public void Reset()
{
timer.Stop();
timer?.Stop();
}
public void Dispose()
@@ -109,7 +109,7 @@ namespace Cysharp.Threading.Tasks
try
{
// stop timer.
timer.Dispose();
timer?.Dispose();
// cancel and dispose.
timeoutSource.Cancel();

View File

@@ -20,8 +20,6 @@ namespace Cysharp.Threading.Tasks
{
ITriggerHandler<T> head; // head.prev is last
ITriggerHandler<T> iteratingHead;
bool preserveRemoveSelf;
ITriggerHandler<T> iteratingNode;
void LogError(Exception ex)
@@ -55,18 +53,9 @@ namespace Cysharp.Threading.Tasks
Remove(h);
}
if (preserveRemoveSelf)
{
preserveRemoveSelf = false;
iteratingNode = null;
var next = h.Next;
Remove(h);
h = next;
}
else
{
h = h.Next;
}
// If `h` itself is removed by OnNext, h.Next is null.
// Therefore, instead of looking at h.Next, the `iteratingNode` reference itself is replaced.
h = h == iteratingNode ? h.Next : iteratingNode;
}
iteratingNode = null;
@@ -97,9 +86,8 @@ namespace Cysharp.Threading.Tasks
LogError(ex);
}
preserveRemoveSelf = false;
var next = h == iteratingNode ? h.Next : iteratingNode;
iteratingNode = null;
var next = h.Next;
Remove(h);
h = next;
}
@@ -132,9 +120,8 @@ namespace Cysharp.Threading.Tasks
LogError(ex);
}
preserveRemoveSelf = false;
var next = h == iteratingNode ? h.Next : iteratingNode;
iteratingNode = null;
var next = h.Next;
Remove(h);
h = next;
}
@@ -167,9 +154,8 @@ namespace Cysharp.Threading.Tasks
LogError(ex);
}
preserveRemoveSelf = false;
var next = h == iteratingNode ? h.Next : iteratingNode;
iteratingNode = null;
var next = h.Next;
Remove(h);
h = next;
}
@@ -241,71 +227,65 @@ namespace Cysharp.Threading.Tasks
{
if (handler == null) throw new ArgumentNullException(nameof(handler));
if (iteratingNode != null && iteratingNode == handler)
var prev = handler.Prev;
var next = handler.Next;
if (next != null)
{
// if remove self, reserve remove self after invoke completed.
preserveRemoveSelf = true;
next.Prev = prev;
}
else
if (handler == head)
{
var prev = handler.Prev;
var next = handler.Next;
if (next != null)
{
next.Prev = prev;
}
if (handler == head)
{
head = next;
}
else if (handler == iteratingHead)
{
iteratingHead = next;
}
else
{
// when handler is head, prev indicate last so don't use it.
if (prev != null)
{
prev.Next = next;
}
}
if (head != null)
{
if (head.Prev == handler)
{
if (prev != head)
{
head.Prev = prev;
}
else
{
head.Prev = null;
}
}
}
if (iteratingHead != null)
{
if (iteratingHead.Prev == handler)
{
if (prev != iteratingHead.Prev)
{
iteratingHead.Prev = prev;
}
else
{
iteratingHead.Prev = null;
}
}
}
handler.Prev = null;
handler.Next = null;
head = next;
}
// when handler is head, prev indicate last so don't use it.
else if (prev != null)
{
prev.Next = next;
}
if (handler == iteratingNode)
{
iteratingNode = next;
}
if (handler == iteratingHead)
{
iteratingHead = next;
}
if (head != null)
{
if (head.Prev == handler)
{
if (prev != head)
{
head.Prev = prev;
}
else
{
head.Prev = null;
}
}
}
if (iteratingHead != null)
{
if (iteratingHead.Prev == handler)
{
if (prev != iteratingHead.Prev)
{
iteratingHead.Prev = prev;
}
else
{
iteratingHead.Prev = null;
}
}
}
handler.Prev = null;
handler.Next = null;
}
}
}

View File

@@ -32,13 +32,11 @@ namespace Cysharp.Threading.Tasks.Triggers
if (cancellationTokenSource == null)
{
cancellationTokenSource = new CancellationTokenSource();
if (!awakeCalled)
{
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, new AwakeMonitor(this));
}
}
if (!awakeCalled)
{
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, new AwakeMonitor(this));
}
return cancellationTokenSource.Token;
}
}
@@ -83,7 +81,7 @@ namespace Cysharp.Threading.Tasks.Triggers
public bool MoveNext()
{
if (trigger.called) return false;
if (trigger.called || trigger.awakeCalled) return false;
if (trigger == null)
{
trigger.OnDestroy();

View File

@@ -8,6 +8,16 @@ namespace Cysharp.Threading.Tasks
{
public static class UniTaskCancellationExtensions
{
#if UNITY_2022_2_OR_NEWER
/// <summary>This CancellationToken is canceled when the MonoBehaviour will be destroyed.</summary>
public static CancellationToken GetCancellationTokenOnDestroy(this MonoBehaviour monoBehaviour)
{
return monoBehaviour.destroyCancellationToken;
}
#endif
/// <summary>This CancellationToken is canceled when the MonoBehaviour will be destroyed.</summary>
public static CancellationToken GetCancellationTokenOnDestroy(this GameObject gameObject)
{
@@ -17,6 +27,13 @@ namespace Cysharp.Threading.Tasks
/// <summary>This CancellationToken is canceled when the MonoBehaviour will be destroyed.</summary>
public static CancellationToken GetCancellationTokenOnDestroy(this Component component)
{
#if UNITY_2022_2_OR_NEWER
if (component is MonoBehaviour mb)
{
return mb.destroyCancellationToken;
}
#endif
return component.GetAsyncDestroyTrigger().CancellationToken;
}
}

View File

@@ -75,6 +75,12 @@ namespace Cysharp.Threading.Tasks
return new UniTask(NextFramePromise.Create(timing, cancellationToken, out var token), token);
}
#if UNITY_2023_1_OR_NEWER
public static async UniTask WaitForEndOfFrame(CancellationToken cancellationToken = default)
{
await Awaitable.EndOfFrameAsync(cancellationToken);
}
#else
[Obsolete("Use WaitForEndOfFrame(MonoBehaviour) instead or UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate). Equivalent for coroutine's WaitForEndOfFrame requires MonoBehaviour(runner of Coroutine).")]
public static YieldAwaitable WaitForEndOfFrame()
{
@@ -86,6 +92,7 @@ namespace Cysharp.Threading.Tasks
{
return UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate, cancellationToken);
}
#endif
public static UniTask WaitForEndOfFrame(MonoBehaviour coroutineRunner, CancellationToken cancellationToken = default)
{
@@ -94,22 +101,34 @@ namespace Cysharp.Threading.Tasks
}
/// <summary>
/// Same as UniTask.Yield(PlayerLoopTiming.FixedUpdate).
/// Same as UniTask.Yield(PlayerLoopTiming.LastFixedUpdate).
/// </summary>
public static YieldAwaitable WaitForFixedUpdate()
{
return UniTask.Yield(PlayerLoopTiming.FixedUpdate);
// use LastFixedUpdate instead of FixedUpdate
// https://github.com/Cysharp/UniTask/issues/377
return UniTask.Yield(PlayerLoopTiming.LastFixedUpdate);
}
/// <summary>
/// Same as UniTask.Yield(PlayerLoopTiming.FixedUpdate, cancellationToken).
/// Same as UniTask.Yield(PlayerLoopTiming.LastFixedUpdate, cancellationToken).
/// </summary>
public static UniTask WaitForFixedUpdate(CancellationToken cancellationToken)
{
return UniTask.Yield(PlayerLoopTiming.FixedUpdate, cancellationToken);
return UniTask.Yield(PlayerLoopTiming.LastFixedUpdate, cancellationToken);
}
public static UniTask DelayFrame(int delayFrameCount, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
public static UniTask WaitForSeconds(float duration, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
{
return Delay(Mathf.RoundToInt(1000 * duration), ignoreTimeScale, delayTiming, cancellationToken);
}
public static UniTask WaitForSeconds(int duration, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
{
return Delay(1000 * duration, ignoreTimeScale, delayTiming, cancellationToken);
}
public static UniTask DelayFrame(int delayFrameCount, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
{
if (delayFrameCount < 0)
{

View File

@@ -137,8 +137,8 @@ namespace Cysharp.Threading.Tasks
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
{
continuation(continuationState);
return true;
}
return true;
}
return false;
@@ -165,8 +165,8 @@ namespace Cysharp.Threading.Tasks
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
{
continuation(continuationState);
return true;
}
return true;
}
return false;
@@ -184,8 +184,8 @@ namespace Cysharp.Threading.Tasks
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
{
continuation(continuationState);
return true;
}
return true;
}
return false;
@@ -328,6 +328,7 @@ namespace Cysharp.Threading.Tasks
}
UniTaskCompletionSourceCore<AsyncUnit> core;
short version;
AutoResetUniTaskCompletionSource()
{
@@ -340,6 +341,7 @@ namespace Cysharp.Threading.Tasks
{
result = new AutoResetUniTaskCompletionSource();
}
result.version = result.core.Version;
TaskTracker.TrackActiveTask(result, 2);
return result;
}
@@ -383,19 +385,19 @@ namespace Cysharp.Threading.Tasks
[DebuggerHidden]
public bool TrySetResult()
{
return core.TrySetResult(AsyncUnit.Default);
return version == core.Version && core.TrySetResult(AsyncUnit.Default);
}
[DebuggerHidden]
public bool TrySetCanceled(CancellationToken cancellationToken = default)
{
return core.TrySetCanceled(cancellationToken);
return version == core.Version && core.TrySetCanceled(cancellationToken);
}
[DebuggerHidden]
public bool TrySetException(Exception exception)
{
return core.TrySetException(exception);
return version == core.Version && core.TrySetException(exception);
}
[DebuggerHidden]
@@ -409,7 +411,6 @@ namespace Cysharp.Threading.Tasks
{
TryReturn();
}
}
[DebuggerHidden]
@@ -451,6 +452,7 @@ namespace Cysharp.Threading.Tasks
}
UniTaskCompletionSourceCore<T> core;
short version;
AutoResetUniTaskCompletionSource()
{
@@ -463,6 +465,7 @@ namespace Cysharp.Threading.Tasks
{
result = new AutoResetUniTaskCompletionSource<T>();
}
result.version = result.core.Version;
TaskTracker.TrackActiveTask(result, 2);
return result;
}
@@ -506,19 +509,19 @@ namespace Cysharp.Threading.Tasks
[DebuggerHidden]
public bool TrySetResult(T result)
{
return core.TrySetResult(result);
return version == core.Version && core.TrySetResult(result);
}
[DebuggerHidden]
public bool TrySetCanceled(CancellationToken cancellationToken = default)
{
return core.TrySetCanceled(cancellationToken);
return version == core.Version && core.TrySetCanceled(cancellationToken);
}
[DebuggerHidden]
public bool TrySetException(Exception exception)
{
return core.TrySetException(exception);
return version == core.Version && core.TrySetException(exception);
}
[DebuggerHidden]
@@ -937,5 +940,5 @@ namespace Cysharp.Threading.Tasks
}
return false;
}
}
}
}

View File

@@ -28,7 +28,7 @@ namespace Cysharp.Threading.Tasks
p.TrySetCanceled();
break;
case TaskStatus.Faulted:
p.TrySetException(x.Exception);
p.TrySetException(x.Exception.InnerException ?? x.Exception);
break;
case TaskStatus.RanToCompletion:
p.TrySetResult(x.Result);
@@ -58,7 +58,7 @@ namespace Cysharp.Threading.Tasks
p.TrySetCanceled();
break;
case TaskStatus.Faulted:
p.TrySetException(x.Exception);
p.TrySetException(x.Exception.InnerException ?? x.Exception);
break;
case TaskStatus.RanToCompletion:
p.TrySetResult();

View File

@@ -133,7 +133,7 @@ namespace Cysharp.Threading.Tasks
{
var self = (ToUniTaskObserver<T>)state;
self.disposable.Dispose();
self.promise.TrySetCanceled();
self.promise.TrySetCanceled(self.cancellationToken);
}
public void OnNext(T value)
@@ -203,7 +203,7 @@ namespace Cysharp.Threading.Tasks
{
var self = (FirstValueToUniTaskObserver<T>)state;
self.disposable.Dispose();
self.promise.TrySetCanceled();
self.promise.TrySetCanceled(self.cancellationToken);
}
public void OnNext(T value)

View File

@@ -21,7 +21,7 @@ namespace Cysharp.Threading.Tasks
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, CancellationToken cancellationToken)
{
return AwaitForAllAssets(asyncOperation, cancellationToken: cancellationToken);
return AwaitForAllAssets(asyncOperation, null, PlayerLoopTiming.Update, cancellationToken: cancellationToken);
}
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))

View File

@@ -15,11 +15,15 @@ namespace Cysharp.Threading.Tasks
{
#region AsyncOperation
#if !UNITY_2023_1_OR_NEWER
// from Unity2023.1.0a15, AsyncOperationAwaitableExtensions.GetAwaiter is defined in UnityEngine.
public static AsyncOperationAwaiter GetAwaiter(this AsyncOperation asyncOperation)
{
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
return new AsyncOperationAwaiter(asyncOperation);
}
#endif
public static UniTask WithCancellation(this AsyncOperation asyncOperation, CancellationToken cancellationToken)
{
@@ -896,7 +900,11 @@ namespace Cysharp.Threading.Tasks
if (asyncOperation.isDone)
{
if (asyncOperation.webRequest.IsError())
if (asyncOperation.webRequest == null)
{
core.TrySetException(new ObjectDisposedException("The webRequest has been destroyed."));
}
else if (asyncOperation.webRequest.IsError())
{
core.TrySetException(new UnityWebRequestException(asyncOperation.webRequest));
}

View File

@@ -673,7 +673,7 @@ namespace Cysharp.Threading.Tasks
}
if (cancellationToken2.CanBeCanceled)
{
registration2 = cancellationToken1.RegisterWithoutCaptureExecutionContext(cancel2, this);
registration2 = cancellationToken2.RegisterWithoutCaptureExecutionContext(cancel2, this);
}
}
@@ -688,13 +688,27 @@ namespace Cysharp.Threading.Tasks
static void OnCanceled1(object state)
{
var self = (UnityEventHandlerAsyncEnumerator)state;
self.DisposeAsync().Forget();
try
{
self.completionSource.TrySetCanceled(self.cancellationToken1);
}
finally
{
self.DisposeAsync().Forget();
}
}
static void OnCanceled2(object state)
{
var self = (UnityEventHandlerAsyncEnumerator)state;
self.DisposeAsync().Forget();
try
{
self.completionSource.TrySetCanceled(self.cancellationToken2);
}
finally
{
self.DisposeAsync().Forget();
}
}
public UniTask DisposeAsync()
@@ -706,6 +720,8 @@ namespace Cysharp.Threading.Tasks
registration1.Dispose();
registration2.Dispose();
unityEvent.RemoveListener(unityAction);
completionSource.TrySetCanceled();
}
return default;
@@ -777,7 +793,7 @@ namespace Cysharp.Threading.Tasks
}
if (cancellationToken2.CanBeCanceled)
{
registration2 = cancellationToken1.RegisterWithoutCaptureExecutionContext(cancel2, this);
registration2 = cancellationToken2.RegisterWithoutCaptureExecutionContext(cancel2, this);
}
}
@@ -793,13 +809,27 @@ namespace Cysharp.Threading.Tasks
static void OnCanceled1(object state)
{
var self = (UnityEventHandlerAsyncEnumerator)state;
self.DisposeAsync().Forget();
try
{
self.completionSource.TrySetCanceled(self.cancellationToken1);
}
finally
{
self.DisposeAsync().Forget();
}
}
static void OnCanceled2(object state)
{
var self = (UnityEventHandlerAsyncEnumerator)state;
self.DisposeAsync().Forget();
try
{
self.completionSource.TrySetCanceled(self.cancellationToken2);
}
finally
{
self.DisposeAsync().Forget();
}
}
public UniTask DisposeAsync()
@@ -815,6 +845,8 @@ namespace Cysharp.Threading.Tasks
disp.Dispose();
}
unityEvent.RemoveListener(unityAction);
completionSource.TrySetCanceled();
}
return default;

View File

@@ -12,17 +12,17 @@ namespace Cysharp.Threading.Tasks
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
// <string> -> Text
public static void BindTo(this IUniTaskAsyncEnumerable<string> source, Text text, bool rebindOnError = true)
public static void BindTo(this IUniTaskAsyncEnumerable<string> source, UnityEngine.UI.Text text, bool rebindOnError = true)
{
BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
}
public static void BindTo(this IUniTaskAsyncEnumerable<string> source, Text text, CancellationToken cancellationToken, bool rebindOnError = true)
public static void BindTo(this IUniTaskAsyncEnumerable<string> source, UnityEngine.UI.Text text, CancellationToken cancellationToken, bool rebindOnError = true)
{
BindToCore(source, text, cancellationToken, rebindOnError).Forget();
}
static async UniTaskVoid BindToCore(IUniTaskAsyncEnumerable<string> source, Text text, CancellationToken cancellationToken, bool rebindOnError)
static async UniTaskVoid BindToCore(IUniTaskAsyncEnumerable<string> source, UnityEngine.UI.Text text, CancellationToken cancellationToken, bool rebindOnError)
{
var repeat = false;
BIND_AGAIN:
@@ -68,22 +68,22 @@ namespace Cysharp.Threading.Tasks
// <T> -> Text
public static void BindTo<T>(this IUniTaskAsyncEnumerable<T> source, Text text, bool rebindOnError = true)
public static void BindTo<T>(this IUniTaskAsyncEnumerable<T> source, UnityEngine.UI.Text text, bool rebindOnError = true)
{
BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
}
public static void BindTo<T>(this IUniTaskAsyncEnumerable<T> source, Text text, CancellationToken cancellationToken, bool rebindOnError = true)
public static void BindTo<T>(this IUniTaskAsyncEnumerable<T> source, UnityEngine.UI.Text text, CancellationToken cancellationToken, bool rebindOnError = true)
{
BindToCore(source, text, cancellationToken, rebindOnError).Forget();
}
public static void BindTo<T>(this AsyncReactiveProperty<T> source, Text text, bool rebindOnError = true)
public static void BindTo<T>(this AsyncReactiveProperty<T> source, UnityEngine.UI.Text text, bool rebindOnError = true)
{
BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
}
static async UniTaskVoid BindToCore<T>(IUniTaskAsyncEnumerable<T> source, Text text, CancellationToken cancellationToken, bool rebindOnError)
static async UniTaskVoid BindToCore<T>(IUniTaskAsyncEnumerable<T> source, UnityEngine.UI.Text text, CancellationToken cancellationToken, bool rebindOnError)
{
var repeat = false;
BIND_AGAIN:

View File

@@ -1,4 +1,4 @@
#if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
#if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
using System;
using System.Collections.Generic;
@@ -49,7 +49,7 @@ namespace Cysharp.Threading.Tasks
{
if (msg == null)
{
if (Text != null)
if(!string.IsNullOrWhiteSpace(Text))
{
msg = Error + Environment.NewLine + Text;
}

View File

@@ -2,7 +2,7 @@
"name": "com.cysharp.unitask",
"displayName": "UniTask",
"author": { "name": "Cysharp, Inc.", "url": "https://cysharp.co.jp/en/" },
"version": "2.3.1",
"version": "2.4.1",
"unity": "2018.4",
"description": "Provides an efficient async/await integration to Unity.",
"keywords": [ "async/await", "async", "Task", "UniTask" ],

View File

@@ -310,33 +310,33 @@ namespace Cysharp.Threading.TasksTests
yield return null;
}
[UnityTest]
public IEnumerator ExceptionUnobserved1() => UniTask.ToCoroutine(async () =>
{
bool calledEx = false;
Action<Exception> action = exx =>
{
calledEx = true;
exx.Message.Should().Be("MyException");
};
//[UnityTest]
//public IEnumerator ExceptionUnobserved1() => UniTask.ToCoroutine(async () =>
//{
// bool calledEx = false;
// Action<Exception> action = exx =>
// {
// calledEx = true;
// exx.Message.Should().Be("MyException");
// };
UniTaskScheduler.UnobservedTaskException += action;
// UniTaskScheduler.UnobservedTaskException += action;
var ex = InException1();
ex = default(UniTask);
// var ex = InException1();
// ex = default(UniTask);
await UniTask.DelayFrame(3);
// await UniTask.DelayFrame(3);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
// GC.Collect();
// GC.WaitForPendingFinalizers();
// GC.Collect();
await UniTask.DelayFrame(1);
// await UniTask.DelayFrame(1);
calledEx.Should().BeTrue();
// calledEx.Should().BeTrue();
UniTaskScheduler.UnobservedTaskException -= action;
});
// UniTaskScheduler.UnobservedTaskException -= action;
//});
[UnityTest]
public IEnumerator ExceptionUnobserved2() => UniTask.ToCoroutine(async () =>