unity3D中協程和線程混合

這是我google unity3D一個問題偶然發現的在stackflow上很有趣的帖子:

大意是 要在unity3D上從服務器下載一個zip,並解壓到持久化地址.並將其加載到內存中.下面展示了這種用法:

IEnumerator LongCoroutine()
{
    yield return StartCoroutine(DownloadZip());
    ExtractZip();
    yield return StartCoroutine(LoadZipContent());
}

但是ExtractZip()方法是同步的,這將掛起進程.結果是無論如何試圖解壓zip,進程將會被殺死.我認爲是主線程太久沒有響應,所以被os殺死.

所以我猜想將提取zip放在單獨線程可能會解決問題,而且看起來這樣奏效了.我寫了這樣一個類:

public class ThreadedAction
{
  public ThreadedAction(Action action)
  {
    var thread = new Thread(() => {
      if(action != null)
        action();
      _isDone = true;
    });
    thread.Start();
  }

  public IEnumerator WaitForComplete()
  {
    while (!_isDone)
      yield return null;
  }

  private bool _isDone = false;
}

如此用它:

IEnumerator LongCoroutine()
{
    yield return StartCoroutine(DownloadZip());
    var extractAction = new ThreadedAction(ExtractZip);
    yield return StartCoroutine(extractAction.WaitForComplete());
    yield return StartCoroutine(LoadZipContent());
}

但是我仍舊不確定這是不是最好的解決辦法.我是否需要鎖定_isDone( not too used to multithreading ).

樓主已經給出解決方法了,原來在球完美之道,哈哈.

下面的跟帖是:

這真是在協程裏糅合多線程的優雅方案.做得好!

Mixing coroutines and threads is perfectly safe, provided you correctly lock access to resources shared between your main thread (which the coroutine executes on) and the worker thread(s) you create. You shouldn't need to lock _isDone in any way, since it's only ever written to by the worker thread and there's no intermediate state that could cause the main thread to misbehave.

混合協程和線程是完全線程安全的,它爲了正確鎖定主線程(協程所在的)和工作線程(可能多個)的共享資源.你不需要鎖定_isDone.因爲它只會在工作線程中寫,沒有交替狀態會引起主線程誤解.

你需要注意的潛在問題是,如果任何資源被ExtractZip寫入,並且

1.同時在主線程裏的一個函數寫入

2.或者在主線程被讀取,只有在ExtracrZip完成後纔是線程安全的.

In this particular case, my worry would be that if you don't check that you're not trying to download the same file to the same location twice, you could have two threads simultaneously running ExtractZip that interfere with one another.

特別情況是,我擔心如果你不去檢測你不會試圖下載同一個文件到同一個位置兩次,你可以有兩個線程並行運行在ExtractZip.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章