【问题标题】:Crash using Mono.Tasklets.Continuation使用 Mono.Tasklets.Continuation 崩溃
【发布时间】:2010-07-14 23:23:31
【问题描述】:

我正在尝试使用单声道在 C# 中处理微线程消息传递库。从 Mono 2.4 左右开始,“Mono.Tasklets”下显然可以使用延续(不是 yield)。但是,这些缺少我能找到的任何文档,虽然我对它们的一般使用有效,但我偶尔会遇到调试器无法附加的(但可重现的)崩溃。

我的具体问题是:

有谁知道 Mark() 函数是什么,以及我需要在何处/何时调用它?好像是一次性的初始化,但是不知道为什么那个时候不会在构造函数中。

使用多个延续是否有限制?我发现您无法将延续传递给另一个线程,但似乎我可以存储多个延续并来回切换?

【问题讨论】:

    标签: c# mono continuations


    【解决方案1】:

    LE:关于崩溃问题,请参阅这些未解决的错误:Bug 566324Bug 580791Bug 602502

    我自己对此很陌生,我在这里介绍我迄今为止收集的信息。也许会有用。

    1) Mono.Tasklets 库(由 Miguel de Icaza [阅读:here] 描述)是一个延续库,可用于构建各种形式的延续系统和轻量级 (LW) 线程。

    一个简单的描述方法是 C 的 longjmp/setjmp 的 Mono 版本,它们只能用于展开堆栈。

    该库最初是由一个人 [阅读:here] 开发的,现在它包含在 Mono 中并记录在案 [阅读:here](点击这些链接,您会找到更多信息)

    那家伙在这个抽象之上实现了一个微线程库。现在已经移植到 Mono.Tasklets 框架

    2) 延续是一个对象,可用于存储当前执行状态,然后可用于稍后恢复存储的状态。

    这里的“执行状态”是指堆栈,包括调用堆栈和局部变量,以及处理器的寄存器。

    当存储的状态被恢复时,程序执行看起来像是跳回了状态被保存的位置,所有的局部变量都被恢复了。

    An example in C.Wikipedia/Continuations 的更多信息

    3) API 是:

    public class Continuation {
          public Continuation ();
          public void Mark ();
          public int Store (int state);
          public void Restore (int state);
     }
    

    Continuations 可用于实现微线程。你可以在 Github 上查看 Mono.MicroThreads 的代码 [阅读:here]

        public Continuation()
        {
            m_handle = alloc_continuation();
            Print("Continuation()");
        }
    
        public void Mark()
        {
            Print("Mark()");
            // skip 1 frame, ie. this function
            mark_continuation_frame(m_handle, 1);
        }
    
        public int Store(int data)
        {
            Print("Store({0})", data);
            int res = store_continuation(m_handle, data);
            Print("Store({0}) = {1}", data, res);
            return res;
        }
    
        public void Restore(int data)
        {
            Print("Restore({0})", data);
            restore_continuation(m_handle, data);
            Print("Restore() exit (NEVER REACHED)");
        }
    

    来自here

    Mark() 用于标记要存储的最顶层帧

    Store(x) 将当前状态存储到延续,并返回给定的整数 x。

    Restore(y) 恢复存储的状态,并返回给定的整数 y。 (请注意,给 Restore 的整数 y 实际上是从 Store() 方法返回的,因为这是我们在状态恢复后所处的位置。)

    static void Main()
    {
     Continuation c = new Continuation();
     c.Mark();
     int foo = 123;
     int val = c.Store(0);
     Console.WriteLine("{0} {1}", val, foo);
     foo = 321;
     if (val < 5)
         c.Restore(val + 1);
    }
    

    当您调用 Store() 时,会记录当前的执行状态,并且可以通过调用 Restore() 回到该状态。

    Store() 的调用者根据 Store 的结果判断它是初始存储还是还原点:

     var c = new Continuation ();
     ...
    
     switch (c.Store (0)){
     case 0:
          // First invocation
     case 1:
          // Restored from the point ahead.
     }
     ...
     // Jump back to the switch statement.
     c.Restore (1); 
    

    【讨论】:

    • monoco 链接 + 尤其是您的摘要非常有帮助 - 谢谢!
    猜你喜欢
    • 1970-01-01
    • 2010-12-06
    • 2015-05-14
    • 2020-12-18
    • 2014-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多