Лавинообразная сложность асинхронных методов
От: Аноним  
Дата: 09.04.12 20:24
Оценка: 1 (1) +1
Есть такая задача:

            // Задача: вызывать Fun и получить "n".
            //
            // После этого последовательны должны быть вызваны:
            //
            // Action2 (кроме случаев, когда "n" не делится на 2)
            // Action3 (кроме случаев, когда "n" не делится на 3)
            // Action4 (кроме случаев, когда "n" не делится на 4)


Задача совершенно практическая. Fun может возвращать список необходимых обновлений, а Action2-Action4 производить эти обновления.

В синхронном варианте это решается так:

            var service = new Service();

            // Синхронный вариант

            {
                int n = service.Fun();

                if (0 == n%2)
                    service.Action2();

                if (0 == n%3)
                    service.Action3();

                if (0 == n%4)
                    service.Action4();

                Console.WriteLine("Complete");
            }


Как видим -- ничего сложного. Можно добавлять сколько угодно Action -- сложность системы от этого не будет возрастать.

А теперь попробуем написать асинхронный вариант. Замечу, что потребность взята не с потолка -- при использовании Windows Phone нет возможности вызова веб-методов синхронно -- только асинхронный вариант. У меня получилось вот что:



            var service = new Service();

            // Асинхронный вариант 1
            {
                service.FunCompleted += (sender, eventArgs) =>
                                                {
                                                    int n = eventArgs.Argument;

                                                    if (0 == n % 2)
                                                    {
                                                        service.Action2Completed +=
                                                            (o, myEventArgs) =>
                                                            {
                                                                if (0 == n % 3)
                                                                {
                                                                    service.Action3Completed
                                                                        += (sender1, args1) =>
                                                                               {
                                                                                   if (0 == n % 4)
                                                                                   {
                                                                                       service.Action4Completed +=
                                                                                           (o1, eventArgs1) =>
                                                                                               {
                                                                                                   Console.WriteLine(
                                                                                                       "Complete");
                                                                                               };

                                                                                       service.StartAction4();
                                                                                   }
                                                                               };

                                                                    service.StartAction3();
                                                                }
                                                                else
                                                                {
                                                                    if (0 == n % 4)
                                                                    {
                                                                        service.Action4Completed +=
                                                                                           (o1, eventArgs1) =>
                                                                                           {
                                                                                               Console.WriteLine(
                                                                                                   "Complete");
                                                                                           };

                                                                        service.StartAction4();
                                                                    }
                                                                }
                                                            };

                                                        service.StartAction2();
                                                    }
                                                    else
                                                    {
                                                        if (0 == n % 3)
                                                        {
                                                            service.Action3Completed
                                                                += (o, myEventArgs) =>
                                                                       {
                                                                           if (0 == n%4)
                                                                           {
                                                                               service.Action4Completed +=
                                                                                           (o1, eventArgs1) =>
                                                                                           {
                                                                                               Console.WriteLine(
                                                                                                   "Complete");
                                                                                           };

                                                                               service.StartAction4();
                                                                           }
                                                                       };

                                                            service.StartAction3();
                                                        }
                                                        else
                                                        {
                                                            if (0 == n % 4)
                                                            {
                                                                service.Action4Completed +=
                                                                                           (o1, eventArgs1) =>
                                                                                           {
                                                                                               Console.WriteLine(
                                                                                                   "Complete");
                                                                                           };

                                                                service.StartAction4();
                                                            }
                                                        }
                                                    }
                                                };

                service.StartFun();
            }



Обратите внимание: сложность нарастает по геометрической прогрессии! Для 3х Action имеем 7 условий. Для 4х их будет в 2 раза больше и так далее...

И, собственно, вопрос. Что делать, если таких вот Action в проекте действительно много? Как быть, как написать? Это ж идиотизм какой-то.

Для удобства привожу упрощенный код полностью:

  Скрытый текст
using System;
using System.Threading;

namespace ConsoleApplication17
{
    class Program
    {
        class MyEventArgs : EventArgs
        {
            public int Argument { get; set; }
        }

        private class Service
        {
            public event EventHandler<MyEventArgs> FunCompleted;

            public event EventHandler Action2Completed;

            public event EventHandler Action3Completed;

            public event EventHandler Action4Completed;

            public void StartFun()
            {
                (new Thread(() =>
                                {
                                    Thread.Sleep(1000);
                                    FunCompleted(this, new MyEventArgs { Argument = DateTime.Now.Second });
                                })).Start();
            }

            public void StartAction2()
            {
                (new Thread(() =>
                                {
                                    Thread.Sleep(1000);
                                    Action2Completed(this, null);
                                })).Start();
            }

            public void StartAction3()
            {
                (new Thread(() =>
                {
                    Thread.Sleep(1000);
                    Action3Completed(this, null);
                })).Start();
            }

            public void StartAction4()
            {
                (new Thread(() =>
                {
                    Thread.Sleep(1000);
                    Action4Completed(this, null);
                })).Start();
            }

            // Синхронный вариант

            public int Fun()
            {
                return DateTime.Now.Second;
            }

            public void Action2()
            {
                
            }

            public void Action3()
            {

            }

            public void Action4()
            {

            }
        }

        static void Main(string[] args)
        {
            // Задача: вызывать Fun 1 и получить "n".
            //
            // После этого последовательны должны быть вызваны:
            //
            // Action2 (кроме случаев, когда "n" не делится на 2)
            // Action3 (кроме случаев, когда "n" не делится на 3)
            // Action4 (кроме случаев, когда "n" не делится на 4)

            var service = new Service();

            // Синхронный вариант

            {
                int n = service.Fun();

                if (0 == n%2)
                    service.Action2();

                if (0 == n%3)
                    service.Action3();

                if (0 == n%4)
                    service.Action4();

                Console.WriteLine("Complete");
            }


            // Асинхронный вариант 1
            {
                service.FunCompleted += (sender, eventArgs) =>
                                                {
                                                    int n = eventArgs.Argument;

                                                    if (0 == n % 2)
                                                    {
                                                        service.Action2Completed +=
                                                            (o, myEventArgs) =>
                                                            {
                                                                if (0 == n % 3)
                                                                {
                                                                    service.Action3Completed
                                                                        += (sender1, args1) =>
                                                                               {
                                                                                   if (0 == n % 4)
                                                                                   {
                                                                                       service.Action4Completed +=
                                                                                           (o1, eventArgs1) =>
                                                                                               {
                                                                                                   Console.WriteLine(
                                                                                                       "Complete");
                                                                                               };

                                                                                       service.StartAction4();
                                                                                   }
                                                                               };

                                                                    service.StartAction3();
                                                                }
                                                                else
                                                                {
                                                                    if (0 == n % 4)
                                                                    {
                                                                        service.Action4Completed +=
                                                                                           (o1, eventArgs1) =>
                                                                                           {
                                                                                               Console.WriteLine(
                                                                                                   "Complete");
                                                                                           };

                                                                        service.StartAction4();
                                                                    }
                                                                }
                                                            };

                                                        service.StartAction2();
                                                    }
                                                    else
                                                    {
                                                        if (0 == n % 3)
                                                        {
                                                            service.Action3Completed
                                                                += (o, myEventArgs) =>
                                                                       {
                                                                           if (0 == n%4)
                                                                           {
                                                                               service.Action4Completed +=
                                                                                           (o1, eventArgs1) =>
                                                                                           {
                                                                                               Console.WriteLine(
                                                                                                   "Complete");
                                                                                           };

                                                                               service.StartAction4();
                                                                           }
                                                                       };

                                                            service.StartAction3();
                                                        }
                                                        else
                                                        {
                                                            if (0 == n % 4)
                                                            {
                                                                service.Action4Completed +=
                                                                                           (o1, eventArgs1) =>
                                                                                           {
                                                                                               Console.WriteLine(
                                                                                                   "Complete");
                                                                                           };

                                                                service.StartAction4();
                                                            }
                                                        }
                                                    }
                                                };

                service.StartFun();
            }


            Console.ReadLine();
        }
    }
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.