c# - 统一错误 : InitWWW can only be called from the main thread

标签 c# setinterval unity3d

我有一个功能可以从文件夹中获取图像并在 RawImage 上显示每个图像 5 秒钟,然后重新开始。

当 looper() 函数调用 medialogic() 函数时显示第一张图像后,我遇到了这个问题。它给出了标题错误。

我该如何解决这个问题或为什么会发生这种情况?我是 unity 和 C# 的新手。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
using System.IO;
using System.Linq;
using System.Text;

public class Test2 : MonoBehaviour {

    // Use this for initialization

    //Publics
    private string path = "file:///";
    public string folder = "C:/medias/";
    int interval = 7000;
    int arrLength;
    int i = 0;

    string source;
    string str;
    WWW www;

    string[] extensions = new[] { ".jpg", ".JPG", ".jpeg", ".JPEG", ".png", ".PNG", ".ogg", ".OGG" };

    FileInfo[] info;
    DirectoryInfo dir;

    void Start() {
        dir = new DirectoryInfo(@folder);
        info = dir.GetFiles().Where(f => extensions.Contains(f.Extension.ToLower())).ToArray();
        arrLength = info.Length;

        looper ();
    }

    // Update is called once per frame
    void Update () {

    }

    void looper() {
        medialogic ();
        EasyTimer.SetInterval(() =>
        {
            if (i == arrLength-1) {
                info = dir.GetFiles().Where(f => extensions.Contains(f.Extension.ToLower())).ToArray();
                arrLength = info.Length;
                i = 0;
            } else {
                i++;
            }
            medialogic();
        }, interval);
    }

    void medialogic() {
        source = info [i].ToString();
        str = path + source;
        www = new WWW(str);
        string[] extType = source.Split('.');
        int pos = Array.IndexOf(extensions, "."+extType[1]);
        if (pos > -1) {
            GetComponent<RawImage> ().texture = www.texture;
            Debug.Log (extType[1]);
        } else {
            //videos here
            Debug.Log (extType[1]);
        }
    }

    public static class EasyTimer
    {
        public static IDisposable SetInterval(Action method, int delayInMilliseconds)
        {
            System.Timers.Timer timer = new System.Timers.Timer(delayInMilliseconds);
            timer.Elapsed += (source, e) =>
            {
                method();
            };

            timer.Enabled = true;
            timer.Start();

            // Returns a stop handle which can be used for stopping
            // the timer, if required
            return timer as IDisposable;
        }

        public static IDisposable SetTimeout(Action method, int delayInMilliseconds)
        {
            System.Timers.Timer timer = new System.Timers.Timer(delayInMilliseconds);
            timer.Elapsed += (source, e) =>
            {
                method();
            };

            timer.AutoReset = false;
            timer.Enabled = true;
            timer.Start();

            // Returns a stop handle which can be used for stopping
            // the timer, if required
            return timer as IDisposable;
        }
    }
}

编辑:下面的用户程序员有正确的答案。

最佳答案

即使这被标记为已解决,但我确实认为您的代码中还有许多其他问题,您现在可能没有注意到但稍后会出现。

使用 InvokeRepeating调用需要让出的 API( WWW ) 是完全错误的。

主要问题是 SetInterval来自 Timer 的功能正在另一个中调用类 Thread但您不能从另一个线程使用 Unity 的 API。

您可以制作 medialogic()函数在主线程中运行 class :

void Awake()
{
    UnityThread.initUnityThread();
}

void looper()
{
    medialogic();
    EasyTimer.SetInterval(() =>
    {
        if (i == arrLength - 1)
        {
            info = dir.GetFiles().Where(f => extensions.Contains(f.Extension.ToLower())).ToArray();
            arrLength = info.Length;
            i = 0;
        }
        else
        {
            i++;
        }

        UnityThread.executeInUpdate(() =>
        {
            medialogic();
        });

    }, interval);
}

这不是您代码中的唯一问题:

您未正确使用 WWW应用程序接口(interface)。它需要在协程函数中使用。在将图像与 GetComponent<RawImage>().texture = www.texture; 一起使用之前,您目前没有等待它完成图像下载。 .

WWW需要协程,协程也可以用于定时器,去掉Timer类并使用 WaitForSeconds在协程函数中等待 5 秒。

正确的做法是:

public class Test2 : MonoBehaviour
{

    // Use this for initialization

    //Publics
    private string path = "file:///";
    public string folder = "C:/medias/";
    int interval = 7000;
    int arrLength;
    int i = 0;

    string source;
    string str;
    WWW www;

    string[] extensions = new[] { ".jpg", ".JPG", ".jpeg", ".JPEG", ".png", ".PNG", ".ogg", ".OGG" };

    FileInfo[] info;
    DirectoryInfo dir;

    void Start()
    {
        dir = new DirectoryInfo(@folder);
        info = dir.GetFiles().Where(f => extensions.Contains(f.Extension.ToLower())).ToArray();
        arrLength = info.Length;

        StartCoroutine(looper());
    }


    IEnumerator looper()
    {
        yield return StartCoroutine(medialogic());

        WaitForSeconds waitTime = new WaitForSeconds(5);

        //Run forever
        while (true)
        {

            if (i == arrLength - 1)
            {
                info = dir.GetFiles().Where(f => extensions.Contains(f.Extension.ToLower())).ToArray();
                arrLength = info.Length;
                i = 0;
            }
            else
            {
                i++;
            }
            yield return StartCoroutine(medialogic());

            //Wait for 5 seconds 
            yield return waitTime;
        }
    }

    IEnumerator medialogic()
    {
        source = info[i].ToString();
        str = path + source;
        www = new WWW(str);

        //Wait for download to finish
        yield return www;

        string[] extType = source.Split('.');
        int pos = Array.IndexOf(extensions, "." + extType[1]);
        if (pos > -1)
        {
            GetComponent<RawImage>().texture = www.texture;
            Debug.Log(extType[1]);
        }
        else
        {
            //videos here
            Debug.Log(extType[1]);
        }
    }
}

关于c# - 统一错误 : InitWWW can only be called from the main thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42646701/

相关文章:

c# - 使用 WCF 和自托管的 Windows 身份验证

javascript - Firebug 错误 : setInterval() Callbacks Cease after Continue from Breakpoint

javascript - setInterval 函数调用的问题

jquery - 间隔触发点击

c# - 从服务器加载时使 Texture2D 在 Unity 中可读

c# - TFS API TeamProjectCollection GetService<IBuildServer>() 返回空对象

c# - 使用变量作为选择器与 Selenium 2 Webdriver by.cssselector

git - git 克隆后损坏的 Unity 项目

c# - 如何将 Linq 结果与 RDLC 报告一起使用?

c# - unity destination Vector 基于旋转和移动量