示例#1
0
        private static void Main(string[] args)
        {
            IActorRuntime runtime = new SimpleActorRuntime();

            Task mainTask = runtime.StartMain(() =>
            {
                // Normal actors.

                // Creates an actor and yields its mailbox.
                // Only the owner of a mailbox can call Receive.
                // Any actor can Send to a mailbox.
                // Every actor has its own mailbox that stores objects.
                IMailbox <object> helloActorMailbox =
                    runtime.Create(() =>
                {
                    IMailbox <object> myMailbox = runtime.CurrentMailbox();

                    object msg = myMailbox.Receive();

                    Console.WriteLine(msg);

                    msg = myMailbox.Receive();

                    Console.WriteLine(msg);

                    IMailbox <string> mailbox =
                        (IMailbox <string>)myMailbox.Receive();

                    mailbox.Send("message for separate mailbox");

                    Console.WriteLine(
                        $"I am actor with mailbox {myMailbox} and I am about to terminate.");

                    return(1);
                });

                helloActorMailbox.Send("hello");
                helloActorMailbox.Send("world");

                // Creates another (separate) mailbox for the current actor.
                // The main mailbox of the current actor is not used in this example.
                // Additional mailboxes can have a more specific type parameter than object.
                IMailbox <string> separateMailbox =
                    runtime.CreateMailbox <string>();

                // send it to helloActor
                helloActorMailbox.Send(separateMailbox);
                // receive a string on this separate mailbox (no casting)
                string textResult = separateMailbox.Receive();
                Console.WriteLine(textResult);


                // Typed actors.

                // Built on top of IActorRuntime
                // (which could be implemented in many ways).
                ITypedActorRuntime typedRuntime =
                    new SimpleTypedActorRuntime(runtime);

                // Create a typed actor: answerPhone is a proxy object.
                // The proxy class for IAnswerPhone is generated dynamically (once)
                // at runtime using System.Reflection.Emit.
                IAnswerPhone answerPhone =
                    typedRuntime.Create <IAnswerPhone>(new AnswerPhone());

                IPhoner phoner1 = typedRuntime.Create <IPhoner>(new Phoner());
                IPhoner phoner2 = typedRuntime.Create <IPhoner>(new Phoner());

                // Send messages to the actors by invoking methods.
                phoner1.Init(1, answerPhone);
                phoner2.Init(2, answerPhone);
                phoner2.Go();
                phoner1.Go();

                // We can use a (lower level) additional mailbox to receive results.
                IMailbox <string> returnMailbox = runtime.CreateMailbox <string>();

                answerPhone.CheckMessages(returnMailbox);
                Console.WriteLine(returnMailbox.Receive());

                // Or we can call methods that return a value, which
                // is similar to the above (current actor is blocked).
                // Methods with a return value can also have `out` and `ref` parameters.
                int b;
                string res = answerPhone.CheckMessagesSync(55, out b, "temp");

                Console.WriteLine(res);

                Console.WriteLine($"b is {b}"); // Should be 3

                // If a method with a return type throws an exception
                // (when executing on another actor), the exception is
                // sent back to us (the caller) and thrown.
                b = 0;
                try
                {
                    res = answerPhone.CheckMessagesSync(56, out b, "temp");
                }
                catch (ArgumentException ex)
                {
                    // The stack trace includes the stack frames from the
                    // other actor.
                    Console.WriteLine(ex);
                    Console.WriteLine($"b is {b}"); // Should be 3
                }
            });

            mainTask.Wait();



            // Random testing (can use actors or typed actors).

            // Do 100 executions of the test case below.

            ITestLauncher testLauncher = new TestLauncher();

            testLauncher.SetScheduler(new RandomScheduler(0));

            for (int i = 1; i <= 100; ++i)
            {
                Console.WriteLine("\n\n... ITERATION " + i + "\n\n");
                testLauncher.Execute((runtime2, testingRuntime) =>
                {
                    IMailbox <object> helloActorMailbox =
                        runtime2.Create(() =>
                    {
                        IMailbox <object> myMailbox =
                            runtime2.CurrentMailbox();

                        object msg = myMailbox.Receive();

                        Console.WriteLine(msg);

                        msg = myMailbox.Receive();

                        Console.WriteLine(msg);

                        IMailbox <string> mailbox =
                            (IMailbox <string>)myMailbox.Receive();

                        mailbox.Send("message for separate mailbox");

                        Console.WriteLine(
                            $"I am actor with mailbox {myMailbox} and I am about to terminate.");

                        return(1);
                    });

                    helloActorMailbox.Send("hello");
                    helloActorMailbox.Send("world");

                    IMailbox <string> separateMailbox =
                        runtime2.CreateMailbox <string>();
                    helloActorMailbox.Send(separateMailbox);
                    Console.WriteLine(separateMailbox.Receive());
                });
            }

            Console.WriteLine("[Done]");
            Console.ReadLine();
        }