teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

別案の提示とGitHubのリンク変更

2020/05/09 06:41

投稿

i-poper
i-poper

スコア12

answer CHANGED
@@ -1,7 +1,7 @@
1
1
  async/await辺りについて私も色々と調べているところで、まだ正確にはつかめてはいませんが、ある程度、目星がついたので回答します。
2
2
 
3
3
 
4
- [こちら](https://github.com/techno-tanoC/progress_test)のソースで言うと、progress.rsの97行目で`Mutex`の`lock()`を呼び出し、`poll()`でlockの獲得をしようとしていますが、これが`Pending`を返した場合に今回の現象が発生しているようです。
4
+ [こちら](https://github.com/techno-tanoC/progress_test/tree/68d09a5849890d8942b3b6158da0e3b6bf51f690)のソースで言うと、progress.rsの97行目で`Mutex`の`lock()`を呼び出し、`poll()`でlockの獲得をしようとしていますが、これが`Pending`を返した場合に今回の現象が発生しているようです。
5
5
 
6
6
  Pendingとなった場合、何らかのイベントで再度タスクを起こして(wake)もらわなければタスクは実行されません。
7
7
  本来であれば他タスクが獲得している`Mutex`のlockが解除された時に起こされ、`poll_write()`が再度呼ばれるはずですが、呼ばれない状態になってしまっているようです。
@@ -13,4 +13,11 @@
13
13
  ```
14
14
  cx.waker().clone().wake();
15
15
  ```
16
- と入れると途中で停止すること無く正常に動作しました。
16
+ と入れると途中で停止すること無く正常に動作しました。
17
+
18
+ [追記]
19
+ 別案として、この用途であれば`tokio::sync::watch`を使うのが良いかなと思いました。以下参照ください。
20
+ [progress_test](https://github.com/i-poper/progress_test/tree/watch)
21
+ フォーマットしてしまったので差分がわかりにくいですが、`poll_write()`でダウンロードの状態が変わったら`watch::Sender.broadcast()`で通知しています。
22
+ ダウンロードキャンセルは、逆にUIスレッド側?から`watch::Sender.broadcast()`で通知します。
23
+ `poll_write()`での参照は`recv()`だと`await`が必要になってしまうので、`watch::Receiver.borrow()`で参照します。