C# 如何编写在每次迭代时暂停的同步任务,以允许线程继续,直到线程再次空闲

C# 如何编写在每次迭代时暂停的同步任务,以允许线程继续,直到线程再次空闲,c#,task,C#,Task,我不确定我想要什么是可能的 我正在为一个主机应用程序编写一个插件,它为我提供了一个我希望处理的对象。限制是我必须只在主机主应用程序线程上处理这些对象。如果我用另一根线碰它们,宿主就会死亡 我已经编写了一个模拟场景,演示了这种情况,并通过评论指出了我想做什么。基本上我得到了一堆要处理的对象。我想做一个任务(我想),它可以在主机空闲时一次迭代处理一个对象,但每次迭代时都会将控制传递回线程,以便主机可以更新其空闲状态(通过事件)如果主机说忙,那么我希望将处理任务挂起,直到主机返回空闲状态 我想象它类似

我不确定我想要什么是可能的

我正在为一个主机应用程序编写一个插件,它为我提供了一个我希望处理的对象。限制是我必须只在主机主应用程序线程上处理这些对象。如果我用另一根线碰它们,宿主就会死亡

我已经编写了一个模拟场景,演示了这种情况,并通过评论指出了我想做什么。基本上我得到了一堆要处理的对象。我想做一个任务(我想),它可以在主机空闲时一次迭代处理一个对象,但每次迭代时都会将控制传递回线程,以便主机可以更新其空闲状态(通过事件)如果主机说忙,那么我希望将处理任务挂起,直到主机返回空闲状态

我想象它类似于下面的代码。但是我不知道如何解决这个问题,我甚至不确定使用
Task/Async
主体是否可能

public class MockHost
{
    public event EventHandler Idle;
    public event EventHandler Busy;
    public event EventHandler<ModifiedObjectsEventArgs> IHaveModifiedObjectsHereYouGo;
}
public class ModifiedObjectsEventArgs: EventArgs
{
    public object[] ModifiedObjects;
}
public class TestClass
{
    MockHost _host = new MockHost();
    ObjectProcessor _processor = new ObjectProcessor();


    public TestClass()
    {
        _host.Idle += _host_Idle;
        _host.Busy += _host_Busy;
        _host.IHaveModifiedObjectsHereYouGo += _host_IHaveModifiedObjectsHereYouGo;
    }

    private async void _host_IHaveModifiedObjectsHereYouGo(object sender, ModifiedObjectsEventArgs e)
    {
         await _processor.ProcessObjectsAsync(e.ModifiedObjects);
    }

    private void _host_Busy(object sender, EventArgs e)
    {
        _processor.SetHostBusyState(true);
    }

    private void _host_Idle(object sender, EventArgs e)
    {
        _processor.SetHostBusyState(false);
    }
}

public class ObjectProcessor
{
    bool _hostIsBusy = false;
    public void SetHostBusyState(bool isBusy)
    {
        _hostIsBusy = isBusy;
        if(!_hostIsBusy)
        {
            // Continue processing.
        }
    }
    public async Task ProcessObjectsAsync(Object[] objects)
    {
        foreach(object obj in objects)
        {
            if (_hostIsBusy)
            {
                // suspend this task somehow
            }
            else
            {
                ProcessObject(obj);
            }
            // suspend the task somehow to let the host events update busy status if they need to.
        }
    }

    private void ProcessObject(object obj)
    {
        // Long running process.
    }
}
公共类MockHost
{
公共事件处理程序空闲;
公共事件处理程序忙;
公共事件处理程序IHaveModifiedObjectsHereYouGo;
}
公共类ModifiedObjectsEventArgs:EventArgs
{
公共对象[]修改对象;
}
公共类TestClass
{
MockHost _host=new MockHost();
ObjectProcessor_processor=新的ObjectProcessor();
公共测试类()
{
_host.Idle+=\u host\u Idle;
_host.Busy+=\u host\u Busy;
_host.IHaveModifiedObjectsHereYouGo+=\u host\u IHaveModifiedObjectsHereYouGo;
}
私有异步void _host_iHaveModifiedObjectShereyYouGo(对象发送方,ModifiedObjectsEventArgs e)
{
wait _processor.ProcessObjectsAsync(e.ModifiedObjects);
}
私有无效\u主机\u忙(对象发送方,事件参数e)
{
_processor.SetHostBusyState(true);
}
私有无效\u主机\u空闲(对象发送方,事件参数e)
{
_processor.SetHostBusyState(false);
}
}
公共类对象处理器
{
bool\u hostIsBusy=false;
public void SetHostBusyState(bool isBusy)
{
_hostIsBusy=isBusy;
如果(!\u主机忙)
{
//继续处理。
}
}
公共异步任务ProcessObjectsAsync(对象[]对象)
{
foreach(对象中的对象对象对象)
{
如果(主机忙)
{
//以某种方式暂停这项任务
}
其他的
{
ProcessObject(obj);
}
//以某种方式挂起任务,以便主机事件在需要时更新忙碌状态。
}
}
私有void ProcessObject(object obj)
{
//长时间运行的过程。
}
}

您可以随时使用以下方法将控制权交还给主机:

await Task.Yield();
这假定主机已设置同步上下文


它所做的是结束当前任务,并将延续发布回同步上下文。通过这种方式,主机可以取回线程,运行它需要的任何代码,然后将控制权交还给您的继续。

而不是在UI线程中执行长时间运行的非UI工作,尝试停止一段时间,让UI事件得到处理,只是不要在UI线程中执行非UI工作,也不要在非UI线程中执行非UI工作。我别无选择,它是由我无法控制的主机强制执行的。我只能在主机应用程序线程上与它的对象进行交互。如果要临时将控制权交还给主机,可以使用
wait Task.Yield()
(假设主机设置了同步上下文)@KevinGosse谢谢我现在正在查看Task.Yield()。你知道如何使用它的好例子吗?@John只是把
wait Task.Yield()放在上面无论您在何处评论“以某种方式暂停任务”