C# - SynchronizationContext vs多线程?

时间:2018-05-24 10:35:44

标签: c# multithreading synchronizationcontext

我想优化我的服务器端速度和性能来管理客户端,我想我有两种方法来管理它们:

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();
        }
    }
}

0 个答案:

没有答案