c# 异步实现方式
2019-02-20 10:16:37 shejiangao 阅读数 140

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;

namespace ConsoleApp5
{
    
    // <summary>
    /// 定义一个委托类型
    /// </summary>
    public delegate string Del();
    /// <summary>
    /// 异步编程实现类(主线程不会阻塞)
    /// </summary>
    public class AsynCallbackClass
    {
        public static string result;

        public static void Main(string[] args)
        {
            Del del = new Del(TaskClass.SleepTask);
            //开始执行异步操作,TaskClass.SleepTask无参数,Callback为定义的回调方法.
            for (int i = 0; i < 2; i++)
            {
                del.BeginInvoke(Callback, null);
            }
        
            Console.ReadLine();
        }

        /// <summary>
        /// 回调方法
        /// </summary>
        /// <param name="ar"></param>
        public static void Callback(IAsyncResult ar)
        {
            AsyncResult asyncResult = ar as AsyncResult;

            if (asyncResult == null) { return; }

            Del del = asyncResult.AsyncDelegate as Del;

            if (del == null) { return; }

            Console.WriteLine("回调方法中调用EndInvoke()方法,获取异步任务结果.\n", Thread.CurrentThread.ManagedThreadId);

            //结束执行异步操作,并返回异步任务结果.
            result = del.EndInvoke(ar);
            Console.WriteLine(result);
        }
    }

    /// <summary>
    /// 任务类
    /// </summary>
    public class TaskClass
    {
        public static string SleepTask()
        {
            Thread.Sleep(5000);
            return "异步线程执行成功.\n" + "---" + DateTime.Now.ToString();
        }
    }
}
 

2016-08-23 14:45:00 weixin_34187862 阅读数 30

 

简单的c# TCP通讯(TcpListener)

C# 的TCP Socket (同步方式)

C# 的TCP Socket (异步方式)

C# 的tcp Socket设置自定义超时时间

C# TCP socket发送大数据包时,接收端和发送端数据不一致 服务端接收Receive不完全

 

 

服务器端:

 

public static ManualResetEvent allDone = new ManualResetEvent(false);

IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port); 
            Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

listener.Bind(localEndPoint);
                listener.Listen(30);
                while (true)
                {
                        allDone.Reset();
                        listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
                        allDone.WaitOne();
                }
public static void AcceptCallback(IAsyncResult ar)
        {
            try
            {
                if (IsListening)
                {
                    allDone.Set();
                    Socket listener = (Socket)ar.AsyncState;
                    Socket handler = listener.EndAccept(ar);
                    StateObject state = new StateObject();
                    state.workSocket = handler;
                    handler.BeginReceive(state.headbuffer, 0, StateObject.HeadBufferSize, 0,
                        new AsyncCallback(ReceiveHead), state);
                }
            }
            catch (System.Exception ex)
            {
                log.ErrorFormat("AcceptCallback异常,原因:{0}", ex.Message);
            }
        }

        private static void ReceiveHead(IAsyncResult ar)
        {
            try
            {
                StateObject state = (StateObject)ar.AsyncState;
                Socket handler = state.workSocket;
                int bytesRead = handler.EndReceive(ar);

                uint length = ByteTouint(state.headbuffer, 3, 4);
                state.length = (int)length - state.headbuffer.Length;
                state.bodybuffer = new byte[length - state.headbuffer.Length];
                handler.BeginReceive(state.bodybuffer, 0, state.bodybuffer.Length, 0,
                        new AsyncCallback(ReadCallback), state);
            }
            catch (System.Exception ex)
            {
                log.ErrorFormat("ReceiveHead异常,原因:{0}", ex.Message + ex.StackTrace);
            }
        }

 

public static void ReadCallback(IAsyncResult ar)
{
            StateObject state = (StateObject)ar.AsyncState;
            Socket handler = state.workSocket;

              int bytesRead = handler.EndReceive(ar);
    //接收的字节在state.bodybuffer里,下面开始处理

}

 

已知接收长度的话可以把ReceiveHead函数去掉,直接进入ReadCallback里。

加入ReceiveHead是因为协议一般在开头几个固定的字节里有后面数据包的长度,所以先接收头,再根据解析出的数据包长度接收后面的。

 

StateObject定义如下,可以不要headbuffer  HeadBufferSize
public class StateObject
    {
        public Socket workSocket = null;
        public const int HeadBufferSize = 7;

        public byte[] headbuffer = new byte[HeadBufferSize];
        public byte[] bodybuffer;
        public int length;
    }

 

客户端发送数据  C# 的TCP Socket (同步方式)

 

2013-09-13 18:52:43 fengxu511 阅读数 699

同步执行模式,是指语句在同步执行模式下,将始终保持对程序流的控制,直至程序结束。例如查询操作,客户机上的应用程序在向服务器发出查询操作的指令后,将一直等待服务器将查询结果返回客户机端后,才继续进行下一步操作;

异步执行模式,是指语句在异步执行模式下,各语句执行结束的顺序与语句执行开始的顺序并不一定相同。例如查询操作,客户机上的应用程序在向服务器发出了查询操作的指令后,将立刻执行查询语句的下一条语句,而不需要等到服务器将查询结果返回客户机端后,才继续进行下一步操作。

1、需要異步執行的方法
public string RunDosCommand(string pCompID, string pFactID, string pDTS, string pDTE, out string sResult)
    {
        string strComm = GetItem_Value("DOS", "Rgui");
        if (strComm == "")
            sResult="";
        strComm = "\"" + strComm + "\"";
        strComm += " -q --no-save --no-restore --args";
        strComm += " " + pCompID + " " + pFactID;
        strComm += " " + pDTS + " " + pDTE;
        Process process = new Process();
        process.StartInfo.FileName = "cmd.exe";
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.RedirectStandardInput = true;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.RedirectStandardError = true;
        process.StartInfo.CreateNoWindow = false;
        process.Start();
        process.StandardInput.WriteLine(strComm);
        process.StandardInput.WriteLine("exit");
        sResult= process.StandardOutput.ReadToEnd();

        return sResult;
    }

2、聲明委托
private delegate string RunDosDelegate(string pCompID, string pFactID, string pDTS, string pDTE, out string sResult);//聲
明RunDosDelegate委托


3、異步
private void MyAsyncCallBack(IAsyncResult iAR)
    {
        string sResult=string.Empty;
        RunDosDelegate runDoc = (RunDosDelegate)iAR.AsyncState;
        runDoc.EndInvoke(out sResult,iAR);
    }
4、執行方法
public string RunDos(string pCompID, string pFactID, string pDTS, string pDTE, out string sResult)
    {
        RunDosDelegate runDos = new RunDosDelegate(RunDosCommand);//設用委托
        AsyncCallback ac = new AsyncCallback(MyAsyncCallBack);//異步呼叫
        IAsyncResult iAResult = runDos.BeginInvoke(pCompID, pFactID, pDTS, pDTE, out sResult , ac, runDos);
        return sResult;
    }

 

2012-05-07 14:59:21 babauyang 阅读数 6824

 

1 多线程概念
目前多数操作系统支持多任务调度和处理, 多任务通常包括两大类: 多进程和多线程。进程是指在系统中正在运行的一个应用程序; 多线程是系统分配处理器时间资源的基本单元, 或者说线程是进程中的基本执行单元。对操作系统而言, 其调度单元是线程。一个进程至少包括一个线程, 称之为主线程。一个进程从主线程的执行开始进而创建一个或多个次线程, 就是所谓基于多线程的多任务。

 

2 多线程的同步与异步
多个线程可能在同一时间对同一共享资源进行操作, 其结果是某个线程将无法获得资源, 或者会导致资源破坏。为保证共享资源的稳定性, 必须采用线程的同步机制。用“锁”来调整多个线程的操作顺序, 一旦某个线程获得“锁”控制权, 可保证只有它才能对共享资源进行操作。同样, 利用这个锁, 某个线程可一直处于等待状态, 直到有能够唤醒信号通过的变量传来为止。

异步是当一个调用请求发送给被调用者, 而调用者不用等待其结果的返回而继续当前的处理, 实现异步机制的方式有多线程、中断、消息等。异步操作在主应用程序线程以外的线程中执行, 应用程序调用方法异步执行某个操作时, 应用程序仍然可继续执行当前程序。异步操作一般用于执行完成时间较长的任务。

 

 

多线程由于有可能对同一共享资源进行访问, 为了协调对共享资源的操作, 需要采用线程同步解决这个问题, 目前有4种线程同步访问共享资源的方式: 一是使用System.Threading.Monitor 类型; 二是C# 语言的Lock关键字, 实际上,C# Lock关键字的底层是使用 Monitor 类实现的; 三是使用System.Threading.Interlocked 类型进行原子型操作; 四是使用[Synchronization]同步化原语。

线程异步编程, 不要忘了委托delegate、BeginInvoke, EndInvoke, AsyncCallBack 委托,AsyncState 实例( 在回调函数中通过IAsyncResult1AsyncState来强制转换), IAsycResult(监控异步), 这样就基本理解异步编程真谛了。异步操作通常用于执行完成时间可能较长的任务, 如打开大文件、连接远程计算机或查询数据库。但应注意, 滥用异步, 会影响性能, 而且增加编程难度, 故应慎重考虑。

2015-02-02 08:35:00 weixin_34223655 阅读数 6
原文:C#实现异步消息队列

拿到新书《.net框架设计》,到手之后迅速读了好多,虽然这本书不像很多教程一样从头到尾系统的讲明一些知识,但是从项目实战角度告诉我们如何使用我们的知识,从这本书中提炼了一篇,正好符合我前几篇的“数据驱动框架”设计的问题;

消息队列

消息队列英语Message queue)是一种进程间通信或同一进程的不同线程间的通信方式,软件贮列用来处理一系列的输入,通常是来自使用者。消息队列提供了异步通信协议,每一个贮列中的纪录包含详细说明的资料,包含发生的时间,输入装置的种类,以及特定的输入参数,也就是说:消息的发送者和接收者不需要同时与消息队列互交。消息会保存在队列中,直到接收者取回它。

简单的说队列就是贮存了我们需要处理的Command但是并不是及时的拿到其处理结果;

实现

实际上,消息队列常常保存在链表结构中。拥有权限的进程可以向消息队列中写入或读取消息。

目前,有很多消息队列有很多开源的实现,包括JBoss MessagingJORAMApache ActiveMQSun Open Message QueueApache Qpid和HTTPSQS。

优点,缺点

消息队列本身是异步的,它允许接收者在消息发送很长时间后再取回消息,这和大多数通信协议是不同的。例如WWW中使用的HTTP协议是同步的,因为客户端在发出请求后必须等待服务器回应。然而,很多情况下我们需要异步的通信协议。比如,一个进程通知另一个进程发生了一个事件,但不需要等待回应。但消息队列的异步特点,也造成了一个缺点,就是接收者必须轮询消息队列,才能收到最近的消息。

信号相比,消息队列能够传递更多的信息。与管道相比,消息队列提供了有格式的数据,这可以减少开发人员的工作量。但消息队列仍然有大小限制。

读取队列消息

主要有两种(1)服务端的推;(2)客户端的拉;

拉:主要是客户端定时轮询拿走消息处理;

推:通过事件订阅方式主动通知订阅者进行处理;

消息的贮存

简单的是通过内存链表实现贮存;也可以借助DB,比如Redis;还可以持久到本地文件中;

如何保证异步处理的一致性

尽管队列主要目的是实现消息贮存,同时将调用与实现异步化。但是如果想达到处理消息一致性,好的方式是区别业务处理顺序,比如操作主从DB,主负责写,从负责读,我们没有机会在写之后立马从读数据库拿到你想要的结果;同时我们需要借助中间状态,当多个中间状态同时符合调用结果才到到业务时间被处理,否则将“异常消息”持久化,待下次操作;

上代码

建立消息对立核心队列

{
    public delegate void MessageQueueEventNotifyHandler(Message.BaseMessage message);

    public class MessageQueue:Queue<BaseMessage>
    {
        public static MessageQueue GlobalQueue = new MessageQueue();

        private Timer timer = new Timer();
        public MessageQueue() {
            this.timer.Interval = 5000;
            this.timer.Elapsed += Notify;
            this.timer.Enabled = true;
        }
        private void Notify(object sender, ElapsedEventArgs e) {
            lock (this) {
                if (this.Count > 0) {
                    //this.messageNotifyEvent.GetInvocationList()[0].DynamicInvoke(this.Dequeue());
                    var message = this.Dequeue();
                    this.messageNotifyEvent(message);
                }
            }
        }

        private MessageQueueEventNotifyHandler messageNotifyEvent;
        public event MessageQueueEventNotifyHandler MessageNotifyEvent {
            add {
                this.messageNotifyEvent += value;
            }

            remove {
                if (this.messageNotifyEvent != null) {
                    this.messageNotifyEvent -= value;
                }
            }
        }
    }
}

事件处理

public const string OrderCodePrefix = "P";
        public void Submit(Message.BaseMessage message)
        {
            Order order = message.Body as Order;

            if (order.OrderCode.StartsWith(OrderCodePrefix))
            {
                System.Console.WriteLine("这个是个正确的以({0})开头的订单:{1}", OrderCodePrefix,order.OrderCode);
            }
            else {
                System.Console.WriteLine("这个是个错误的订单,没有以({0})开头:{1}",OrderCodePrefix,order.OrderCode);
            }
        }

可依据具体业务进行个性化处理;

通过Proxy向队列追加消息

public class OrderServiceProxy:IOrderService
    {
        public void Submit(Message.BaseMessage message)
        {
            MessageQueue.MessageQueue.GlobalQueue.Enqueue(message);
        }
    }

客户端调用

OrderService orderService = new OrderService();
            MessageQueue.MessageQueue.GlobalQueue.MessageNotifyEvent += orderService.Submit;

            var orders = new List<Order>() { 
                new Order(){OrderCode="P001"},
                new Order(){OrderCode="P002"},
                new Order(){OrderCode="B003"}
            };

            OrderServiceProxy proxy = new OrderServiceProxy();
            orders.ForEach(order => proxy.Submit(new Message.BaseMessage() { Body=order}));

            Console.ReadLine();

这样就满足了事件的绑定与触发个性化处理,同时达到了消息异步化的目的,希望更细致的拓展用到后期的项目中。

C# 异步实现方法调用

阅读数 396

异步?usingSystem;usingSystem.Web;usingSystem.Threading;classHelloWorldAsyncHandler:IHttpAsyncHandler{publicboolIsReusable{get{returnfalse;}}publicHelloWorldAsyncHandl

博文 来自: likunran521

C#实现异步消息队列

阅读数 25

原文:C#实现异步消息队列拿到新书《.net框架设计》,到手之后迅速读了好多,虽然这本书不像很多教程一样从头到尾系统的讲明一些知识,但是从项目实战角度告诉我们如何使用我们的知识,从这本书中提炼了一篇,正好符合我前几篇的“数据驱动框架”设计的问题;消息队列消息队列(英语:Messagequeue)是一种进程间通信或同一进程的不同线程间的通信方式,软件的贮列用来处理一系列的输入,通常是来...

博文 来自: weixin_34071713

C#异步:实现一个最简单的异步

阅读数 15444

异步就是方法异步执行,这个好理解。异步有啥用?以前只是听说过,也不想计较。不过还是碰到了需要这个东西的时候。 比如:定时执行,如果不用异步方法,也不用定时器,只用Thread.Sleep来间隔。执行方法本身需要时间,这样定时的意义就变了——两次的执行时间肯定相隔不止1分钟了。

博文 来自: yenange

C# Tcp通信服务器的同步和异步方式

阅读数 4165

一、同步和异步同步和异步指的是在处理TCP连接时采用阻塞式还是非阻塞式进行处理。阻塞式即同步处理方式为:在侦听服务器端口时程序死在侦听阶段,类似于一个while(true)的死循环,直到有新的连接请求接入时,才会break出这个死循环,程序才会向下一步运行。非阻塞式即异步处理方式为:在侦听服务器端口并非死等的方式,而是放在程序运行的后台,直到有新的连接请求接入时,自动调用一个回调函数来

博文 来自: u013352994

C# 创建线程的简单方式:异步委托 .

阅读数 6

定义一个委托调用的方法:TakesAWhile[c-sharp]viewplaincopyprint?//定义委托要引用的方法  private static int TakesAWhile(int data, int ms)  {      Console.WriteLine("开始...");        //当前线程(委托线程)阻塞ms毫秒...

博文 来自: weixin_33928467
没有更多推荐了,返回首页