如果在 Avalonia 後臺程式碼播放一個動畫,這個動畫的 Animation 的 IterationCount 被設定為 Infinite 那麼將在播放的時候丟擲 InvalidOperationException 異常
本文所使用的 Avalonia 為 11.1.0 版本,由於 Avalonia 行為和 API 變動較多,如大家使用其他版本還請重新測試
如以下程式碼,將會丟擲 InvalidOperationException 異常
var content = Content;
var textBlock = (TextBlock) content!;
var animation = new Animation()
{
Duration = TimeSpan.FromSeconds(10),
IterationCount = IterationCount.Infinite,
PlaybackDirection = PlaybackDirection.Alternate,
Children =
{
new KeyFrame()
{
Setters =
{
new Setter(TranslateTransform.XProperty, 0d),
},
KeyTime = TimeSpan.FromSeconds(0)
},
new KeyFrame()
{
Setters =
{
new Setter(TranslateTransform.XProperty, 500d),
},
KeyTime = TimeSpan.FromSeconds(10)
}
}
};
textBlock.RenderTransform = new TranslateTransform();
await animation.RunAsync(textBlock);
以上程式碼是從 Avalonia 後臺程式碼簡單播放動畫示例 修改的
執行以上程式碼,將可以看到如下錯誤資訊
System.InvalidOperationException:“Looping animations must not use the Run method.”
經過閱讀 Avalonia 的程式碼,我理解了 Avalonia 的意圖。在 Avalonia 裡面,認為如果一個動畫是無限播放的,那就不應該使用 RunAsync 等待,防止等待的邏輯永不返回
然而 Avalonia 卻允許呼叫 RunAsync 方法播放動畫,換句話說就是隻要使用 RunAsync 而不進行等待就不會炸掉
只需將 await animation.RunAsync(textBlock);
修改為 _ = animation.RunAsync(textBlock);
即可
如果即可執行一個無限播放的動畫
我認為這是 Avalonia 的設計問題,但是不太確定,於是就在 Avalonia 提了一個討論
詳細請看 https://github.com/AvaloniaUI/Avalonia/discussions/16757
為什麼不等待 RunAsync 也可以?這是因為在 RunAsync 裡面是採用 TaskCompletionSource 作為等待機制,判斷如果是無限迴圈的動畫,則設定 TaskCompletionSource 異常而已
var run = new TaskCompletionSource<object?>();
if (this.IterationCount == IterationCount.Infinite)
run.SetException(new InvalidOperationException("Looping animations must not use the Run method."));
這就意味著在不等待 RunAsync 時,將只是 TaskCompletionSource 被設定異常狀態,不會真的出現任何異常。也就是儘管 InvalidOperationException 被 new 了,但是沒有地方丟擲
本文程式碼放在 github 和 gitee 上,可以使用如下命令列拉取程式碼。我整個程式碼倉庫比較龐大,使用以下命令列可以進行部分拉取,拉取速度比較快
先建立一個空資料夾,接著使用命令列 cd 命令進入此空資料夾,在命令列裡面輸入以下程式碼,即可獲取到本文的程式碼
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 2b7efe38fb648e446b13d9449c92ae5bd4e7cd9a
以上使用的是國內的 gitee 的源,如果 gitee 不能訪問,請替換為 github 的源。請在命令列繼續輸入以下程式碼,將 gitee 源換成 github 源進行拉取程式碼。如果依然拉取不到程式碼,可以發郵件向我要程式碼
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 2b7efe38fb648e446b13d9449c92ae5bd4e7cd9a
獲取程式碼之後,進入 AvaloniaIDemo/LicajearyaWenewernichiji 資料夾,即可獲取到原始碼
更多技術部落格,請參閱 部落格導航