在我的BackgroundWorker
中,我需要使用非线程保存API定期构造和处理各种数据。我知道可以在主线程上使用Actions队列调用,但我不知道如何从这个队列中返回一个值。
那怎么可能呢?或者是否有比BackgroundWorker
更好的方法?
到目前为止我只找到了this.Invoke
的问题,但我无法使用它们,因为API(Unity 5引擎)不能提供类似的功能。
顺便说一下,我的环境只支持.NET 2.0。
编辑:我可能需要提供一些示例
假设只能从mainthread调用Foo
的构造函数,我需要这样做
TheInvokeMethode(() => { FooArray[i] = new Foo();});
SomeMethode(FooArray[i]);
只能从MainThread调用或假设AddComponent()
Bar
Bar SomeBar;
TheInvokeMethode(() => { SomeBar.AddComponent()});
然而,TheInvokeMethode
只是表达包含代码应该在MainThread上执行的东西。
答案 0 :(得分:1)
在Unity中,您可以创建自己的Invoke,其工作方式与Control.Invoke相同:
using System;
using System.Threading;
public class UnityInvoker : MonoBehaviour
{
public UnityInvoker Instance { get; private set; }
void Awake()
{
Instance = this;
_updateThread = Thread.CurrentThread;
}
Action _stored;
object _lock = new object();
volatile Thread _updateThread;
public void Invoke(Action action)
{
if (_updateThread == Thread.CurrentThread)
{
lock (_lock) _stored += action;
Update();
return;
}
using (var waiter = new ManualResetEvent(false))
{
action += () => waiter.Set();
lock (_lock)
_stored += action;
waiter.WaitOne();
}
}
void Update()
{
_updateThread = Thread.CurrentThread;
Action toDo;
lock (_lock)
{
toDo = _stored;
_stored = null;
}
if (toDo != null)
toDo();
}
}
将它放在任何游戏对象上。
用法:
UnityInvoker.Instance.Invoke(()=>Application.Quit());
可以使用Interlocked进行优化(如果需要)。
答案 1 :(得分:0)
BackgroundWorker确实有一个ReportProgress方法可以触发您可以订阅的ProgressChanged事件。
一个重载接受"对象"作为用户 - 您可以使用它来报告您的中间数据。
答案 2 :(得分:0)
有一个对象存储这些值的问题是什么?也许还有其他一些表明这些价值观发生了变化?
通过适当的锁定,这不应该是一个问题
假设您已经可以在主线程中调用您的操作(如果没有,sql_auto_is_null
可能会提供一些帮助,虽然我从未使用过Unity,因此您需要信任用户统一论坛),您可以使用如下模式:
某处:
// ... perform your actions here ...
lock(MyResult)
{
MyResult = <data you want to gather on your thread>;
MyResultIsModified = true;
}
在主线程的代码中:
lock(MyResult)
{
if(MyResultIsModified)
{
// ... do whatever with MyResult ..
MyResultIsModified = false;
}
}
在你的线程/ backgroundworker /无论循环中:
MyResult
如果NSArrayController
是值类型,那么您需要为锁定目的设置另一个对象,但是关于它