Синхронизация Context против многопоточности? - PullRequest
0 голосов
/ 24 мая 2018

Я хочу оптимизировать скорость и производительность моей серверной части для управления клиентами, я думаю, что у меня есть два способа управления ими:

1.Создать вручную один поток на соединение клиента

2.создать SynchronizationContext для каждого клиента (это будет управлять потоками в фоновом режиме)

Предположим, у нас подключен миллион пользователей:

Первый способ быстрее, но я не знаю, оптимизировать и лучше управлятьотправлять / получать данные от клиента или нет?

Что вы предлагаете для повышения производительности и скорости управления всеми клиентами без задержек и зависаний?

Мой пример тестирования SynchronizationContext и многопоточности наконсоль:

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SynchronizationContextForMethod
{

    public class ServiceClass
    {
        public void Login(string name)
        {
            OperationContext<ClientInfo>.Current = new ClientInfo() { Name = name };
        }

        public string WhatIsMyName()
        {
            return OperationContext<ClientInfo>.Current.Name;
        }
    }

    public class ClientInfo
    {
        public string Name { get; set; }
        public string UserName { get; set; }
    }

    public class OperationContext<T>
    {
        static ConcurrentDictionary<SynchronizationContext, T> ContextByThread = new ConcurrentDictionary<SynchronizationContext, T>();
        public static T Current
        {
            get
            {
                ContextByThread.TryGetValue(SynchronizationContext.Current, out T value);
                return value;
            }
            set
            {
                ContextByThread.TryAdd(SynchronizationContext.Current, value);
            }
        }

        public static void EncContext()
        {
            ContextByThread.TryRemove(SynchronizationContext.Current, out T value);
        }
    }

    class Program
    {
        static List<SynchronizationContext> _contexts = new List<SynchronizationContext>();
        static void Main(string[] args)
        {
            ThreadPool.GetMaxThreads(out int worker, out int ports);

            ThreadPool.SetMaxThreads(int.MaxValue, int.MaxValue);
            Console.WriteLine("thread count : " + Process.GetCurrentProcess().Threads.Count);

            SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
            _contexts.Add(SynchronizationContext.Current);
            var service = new ServiceClass();

            for (int i = 0; i < 20; i++)
            {
                //PostWithNewThread((state) =>
                PostNormally((state) =>
                {
                    GC.Collect();
                    if (SynchronizationContext.Current == null)
                    {
                        SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
                    }
                    else
                    {
                        //no run ever
                    }
                    Console.WriteLine("thread count : " + Process.GetCurrentProcess().Threads.Count);
                    var name = state.ToString();
                    service.Login(name);
                    var isTrue = name == service.WhatIsMyName();
                    if (!isTrue)
                    {
                        //if false this is wrong code!
                    }
                    Console.WriteLine($"service login {name}: " + isTrue);
                    Thread.Sleep(5000);
                    Console.WriteLine($"service " + name + " finished");
                    OperationContext<ClientInfo>.EncContext();
                }, "ali" + i);
                Console.WriteLine("thread count : " + Process.GetCurrentProcess().Threads.Count);

                //PostWithNewThread((state) =>
                PostNormally((state) =>
                {
                    GC.Collect();
                    if (SynchronizationContext.Current == null)
                    {
                        SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
                    }
                    else
                    {
                        //no run ever
                    }
                    Console.WriteLine("thread count : " + Process.GetCurrentProcess().Threads.Count);
                    var name = state.ToString();
                    service.Login(name);
                    var isTrue = name == service.WhatIsMyName();
                    if (!isTrue)
                    {
                        //if false this is wrong code!
                    }
                    Console.WriteLine($"service login {name}: " + isTrue);
                    Console.WriteLine($"service " + name + " finished");
                    OperationContext<ClientInfo>.EncContext();
                }, "reza" + i);
                Console.WriteLine("thread count : " + Process.GetCurrentProcess().Threads.Count);

                //PostWithNewThread((state) =>
                PostNormally((state) =>
                {
                    GC.Collect();
                    if (SynchronizationContext.Current == null)
                    {
                        SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
                    }
                    else
                    {
                        //no run ever
                    }
                    Console.WriteLine("thread count : " + Process.GetCurrentProcess().Threads.Count);
                    Thread.Sleep(2000);
                    var name = state.ToString();
                    service.Login(name);
                    var isTrue = name == service.WhatIsMyName();
                    if (!isTrue)
                    {
                        //if false this is wrong code!
                    }
                    Console.WriteLine($"service login {name}: " + (isTrue));
                    Console.WriteLine($"service " + name + " finished");
                    OperationContext<ClientInfo>.EncContext();
                }, "hassan" + i);
            }
            Console.WriteLine("thread count : " + Process.GetCurrentProcess().Threads.Count);
            while (true)
            {
                GC.Collect();
                Thread.Sleep(1000);
                Console.WriteLine("thread count : " + Process.GetCurrentProcess().Threads.Count);
            }
        }

        public static void PostNormally(SendOrPostCallback run, object state)
        {
            SynchronizationContext.Current.Post(run, state);
        }

        public static void PostWithNewThread(SendOrPostCallback run, object state)
        {
            Thread thread = new Thread(() =>
            {
                run(state);
            });
            thread.IsBackground = true;
            thread.Start();
        }
    }
}
...