您的位置:

首页 >

365体育官网备用网址 >

c#文档图片自动纠偏 >

c#文档图片自动纠偏

2016-07-28 01:16:27

分类:365体育官网备用网址

复制代码 代码如下:public class Deskew    {        // Representation of a line in the image.          private class HougLine        {            // Count of points in the line.            public int Count;            // Index in Matrix.            public int Index;            // The line is represented as all x,y that solve y*cos(alpha)-x*sin(alpha)=d            public double Alpha;        }        // The Bitmap        public Bitmap _internalBmp;        // The range of angles to search for lines        const double ALPHA_START = -20;        const double ALPHA_STEP = 0.2;        const int STEPS = 40 * 5;        const double STEP = 1;        // Precalculation of sin and cos.        double[] _sinA;        double[] _cosA;        // Range of d        double _min;        int _count;        // Count of points that fit in a line.        int[] _hMatrix;        // Calculate the skew angle of the image cBmp.        public double GetSkewAngle()        {            // Hough Transformation            Calc();            // Top 20 of the detected lines in the image.            HougLine[] hl = GetTop(20);            // Average angle of the lines            double sum = 0;            int count = 0;            for (int i = 0; i <= 19; i++)            {                sum += hl[i].Alpha;                count += 1;            }            return sum / count;        }        // Calculate the Count lines in the image with most points.        private HougLine[] GetTop(int count)        {            HougLine[] hl = new HougLine[count];            for (int i = 0; i <= count - 1; i++)            {                hl[i] = new HougLine();            }            for (int i = 0; i <= _hMatrix.Length - 1; i++)            {                if (_hMatrix[i] > hl[count - 1].Count)                {                    hl[count - 1].Count = _hMatrix[i];                    hl[count - 1].Index = i;                    int j = count - 1;                    while (j > 0 && hl[j].Count > hl[j - 1].Count)                    {                        HougLine tmp = hl[j];                        hl[j] = hl[j - 1];                        hl[j - 1] = tmp;                        j -= 1;                    }                }            }            for (int i = 0; i <= count - 1; i++)            {                int dIndex = hl[i].Index / STEPS;                int alphaIndex = hl[i].Index - dIndex * STEPS;                hl[i].Alpha = GetAlpha(alphaIndex);                //hl[i].D = dIndex + _min;            }            return hl;        }        // Hough Transforamtion:        private void Calc()        {            int hMin = _internalBmp.Height / 4;            int hMax = _internalBmp.Height * 3 / 4;            Init();            for (int y = hMin; y <= hMax; y++)            {                for (int x = 1; x <= _internalBmp.Width - 2; x++)                {                    // Only lower edges are considered.                    if (IsBlack(x, y))                    {                        if (!IsBlack(x, y + 1))                        {                            Calc(x, y);                        }                    }                }            }        }        // Calculate all lines through the point (x,y).        private void Calc(int x, int y)        {            int alpha;            for (alpha = 0; alpha <= STEPS - 1; alpha++)            {                double d = y * _cosA[alpha] - x * _sinA[alpha];                int calculatedIndex = (int)CalcDIndex(d);                int index = calculatedIndex * STEPS + alpha;                try                {                    _hMatrix[index] += 1;                }                catch (Exception ex)                {                    System.Diagnostics.Debug.WriteLine(ex.ToString());                }            }        }        private double CalcDIndex(double d)        {            return Convert.ToInt32(d - _min);        }        private bool IsBlack(int x, int y)        {            Color c = _internalBmp.GetPixel(x, y);            double luminance = (c.R * 0.299) + (c.G * 0.587) + (c.B * 0.114);            return luminance < 140;        }        private void Init()        {            // Precalculation of sin and cos.            _cosA = new double[STEPS];            _sinA = new double[STEPS];            for (int i = 0; i < STEPS; i++)            {                double angle = GetAlpha(i) * Math.PI / 180.0;                _sinA[i] = Math.Sin(angle);                _cosA[i] = Math.Cos(angle);            }            // Range of d:                        _min = -_internalBmp.Width;            _count = (int)(2 * (_internalBmp.Width + _internalBmp.Height) / STEP);            _hMatrix = new int[_count * STEPS];        }        private static double GetAlpha(int index)        {            return ALPHA_START + index * ALPHA_STEP;        }    }自己写的调用方法复制代码 代码如下:public static void DeskewImage(string fileName, byte binarizeThreshold)        {            //打开图像            Bitmap bmp = OpenImage(fileName);            Deskew deskew = new Deskew();            Bitmap tempBmp = CropImage(bmp, bmp.Width / 4, bmp.Height / 4, bmp.Width / 2, bmp.Height / 2);            deskew._internalBmp = BinarizeImage(tempBmp, binarizeThreshold);            double angle = deskew.GetSkewAngle();            bmp = RotateImage(bmp, (float)(-angle));            //保存图像(需要再还原图片原本的位深度)            SaveImage(bmp, fileName);        }        /// <summary>        /// 图像剪切        /// </summary>        /// <param name="bmp"></param>        /// <param name="StartX"></param>        /// <param name="StartY"></param>        /// <param name="w"></param>        /// <param name="h"></param>        /// <returns></returns>        private static Bitmap CropImage(Bitmap bmp, int StartX, int StartY, int w, int h)        {            try            {                Bitmap bmpOut = new Bitmap(w, h, PixelFormat.Format32bppArgb);                Graphics g = Graphics.FromImage(bmpOut);                g.DrawImage(bmp, new Rectangle(0, 0, w, h), new Rectangle(StartX, StartY, w, h), GraphicsUnit.Pixel);                g.Dispose();                return bmpOut;            }            catch            {                return null;            }        }        /// <summary>        /// 图像二值化        /// </summary>        /// <param name="b"></param>        /// <param name="threshold">阈值</param>        private static Bitmap BinarizeImage(Bitmap b, byte threshold)        {            int width = b.Width;            int height = b.Height;            BitmapData data = b.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);            unsafe            {                byte* p = (byte*)data.Scan0;                int offset = data.Stride - width * 4;                byte R, G, B, gray;                for (int y = 0; y < height; y++)                {                    for (int x = 0; x < width; x++)                    {                        R = p[2];                        G = p[1];                        B = p[0];                        gray = (byte)((R * 19595 + G * 38469 + B * 7472) >> 16);                        if (gray >= threshold)                        {                            p[0] = p[1] = p[2] = 255;                        }                        else                        {                            p[0] = p[1] = p[2] = 0;                        }                        p += 4;                    }                    p += offset;                }                b.UnlockBits(data);                return b;            }        }        /// <summary>        /// 图像旋转        /// </summary>        /// <param name="bmp"></param>        /// <param name="angle">角度</param>        /// <returns></returns>        private static Bitmap RotateImage(Bitmap bmp, float angle)        {            PixelFormat pixelFormat = bmp.PixelFormat;            PixelFormat pixelFormatOld = pixelFormat;            if (bmp.Palette.Entries.Count() > 0)            {                pixelFormat = PixelFormat.Format24bppRgb;            }            Bitmap tmpBitmap = new Bitmap(bmp.Width, bmp.Height, pixelFormat);            tmpBitmap.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);            Graphics g = Graphics.FromImage(tmpBitmap);            try            {                g.FillRectangle(Brushes.White, 0, 0, bmp.Width, bmp.Height);                g.RotateTransform(angle);                g.DrawImage(bmp, 0, 0);            }            catch            {            }            finally            {                g.Dispose();            }            if (pixelFormatOld == PixelFormat.Format8bppIndexed) tmpBitmap = CopyTo8bpp(tmpBitmap);            else if (pixelFormatOld == PixelFormat.Format1bppIndexed) tmpBitmap = CopyTo1bpp(tmpBitmap);            return tmpBitmap;        }在最后进行图片选择时,位深度为1、4、8的索引图片是没办法直接用Graphics进行旋转操作的,需要图像的PixelFormat再做旋转。现在只实现位深度为1和8的索引图片还原。复制代码 代码如下:private static Bitmap CopyTo1bpp(Bitmap b)        {            int w = b.Width, h = b.Height; Rectangle r = new Rectangle(0, 0, w, h);            if (b.PixelFormat != PixelFormat.Format32bppPArgb)            {                Bitmap temp = new Bitmap(w, h, PixelFormat.Format32bppPArgb);                temp.SetResolution(b.HorizontalResolution, b.VerticalResolution);                Graphics g = Graphics.FromImage(temp);                g.DrawImage(b, r, 0, 0, w, h, GraphicsUnit.Pixel);                g.Dispose();                b = temp;            }            BitmapData bdat = b.LockBits(r, ImageLockMode.ReadOnly, b.PixelFormat);            Bitmap b0 = new Bitmap(w, h, PixelFormat.Format1bppIndexed);            b0.SetResolution(b.HorizontalResolution, b.VerticalResolution);            BitmapData b0dat = b0.LockBits(r, ImageLockMode.ReadWrite, PixelFormat.Format1bppIndexed);            for (int y = 0; y < h; y++)            {                for (int x = 0; x < w; x++)                {                    int index = y * bdat.Stride + (x * 4);                    if (Color.FromArgb(Marshal.ReadByte(bdat.Scan0, index + 2), Marshal.ReadByte(bdat.Scan0, index + 1), Marshal.ReadByte(bdat.Scan0, index)).GetBrightness() > 0.5f)                    {                        int index0 = y * b0dat.Stride + (x >> 3);                        byte p = Marshal.ReadByte(b0dat.Scan0, index0);                        byte mask = (byte)(0x80 >> (x & 0x7));                        Marshal.WriteByte(b0dat.Scan0, index0, (byte)(p | mask));                    }                }            }            b0.UnlockBits(b0dat);            b.UnlockBits(bdat);            return b0;        }        private static Bitmap CopyTo8bpp(Bitmap bmp)        {            if (bmp == null) return null;            Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);            BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);            int width = bmpData.Width;            int height = bmpData.Height;            int stride = bmpData.Stride;            int offset = stride - width * 3;            IntPtr ptr = bmpData.Scan0;            int scanBytes = stride * height;            int posScan = 0, posDst = 0;            byte[] rgbValues = new byte[scanBytes];            Marshal.Copy(ptr, rgbValues, 0, scanBytes);            byte[] grayValues = new byte[width * height];            for (int i = 0; i < height; i++)            {                for (int j = 0; j < width; j++)                {                    double temp = rgbValues[posScan++] * 0.11 +                        rgbValues[posScan++] * 0.59 +                        rgbValues[posScan++] * 0.3;                    grayValues[posDst++] = (byte)temp;                }                posScan += offset;            }            Marshal.Copy(rgbValues, 0, ptr, scanBytes);            bmp.UnlockBits(bmpData);            Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format8bppIndexed);            bitmap.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);            BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);            int offset0 = bitmapData.Stride - bitmapData.Width;            int scanBytes0 = bitmapData.Stride * bitmapData.Height;            byte[] rawValues = new byte[scanBytes0];            int posSrc = 0;            posScan = 0;            for (int i = 0; i < height; i++)            {                for (int j = 0; j < width; j++)                {                    rawValues[posScan++] = grayValues[posSrc++];                }                posScan += offset0;            }            Marshal.Copy(rawValues, 0, bitmapData.Scan0, scanBytes0);            bitmap.UnlockBits(bitmapData);            ColorPalette palette;            using (Bitmap bmp0 = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))            {                palette = bmp0.Palette;            }            for (int i = 0; i < 256; i++)            {                palette.Entries[i] = Color.FromArgb(i, i,

闲来无事想玩玩双向通信,实现类似QQ的互发消息的功能。于是乎开始学习.Net Remoting..Net Remoting 是由客户端通过Remoting,访问通道以获得服务端对象,再通过代理解析为客户端对象来实现通信的。也就是说对象是由服务端创建的。先上代码首先是ICommand库using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ICommand{ public interface IRemotingObject { event SendHandler ClientToServer; event ReceiveHandler ServerToClient; event UserChangedHandler Login; event UserChangedHandler Exit; /// <summary> /// 加法运算 /// </summary> /// <param name="x1">参数1</param> /// <param name="x2">参数2</param> /// <returns></returns> string SUM(int x1, int x2); /// <summary> /// 获取服务端事件列表 /// </summary> Delegate[] GetServerEventList(); /// <summary> /// 发送消息 /// </summary> /// <param name="info"></param> /// <param name="toName"></param> void ToServer(object info, string toName); /// <summary> /// 接受信息 /// </summary> /// <param name="info"></param> /// <param name="toName"></param> void ToClient(object info, string toName); void ToLogin(string name); void ToExit(string name); } /// <summary> /// 客户端发送消息 /// </summary> /// <param name="info">信息</param> /// <param name="toName">发送给谁,""表示所有人,null表示没有接收服务器自己接收,其他表示指定某人</param> public delegate void SendHandler(object info, string toName); /// <summary> /// 客户端接收消息 /// </summary> /// <param name="info">信息</param> /// <param name="toName">发送给谁,""表示所有人,null表示没有接收服务器自己接收,其他表示指定某人</param> public delegate void ReceiveHandler(object info, string toName); /// <summary> /// 用户信息事件 /// </summary> /// <param name="name">用户名</param> public delegate void UserChangedHandler(string name);}using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ICommand{ public class SwapObject : MarshalByRefObject { public event ReceiveHandler SwapServerToClient { add { _receive += value; } remove { _receive -= value; } } /// <summary> /// 接受信息 /// </summary> /// <param name="info"></param> /// <param name="toName"></param> public void ToClient(object info, string toName) { if (_receive != null) _receive(info, toName); } //无限生命周期 public override object InitializeLifetimeService() { return null; } private ReceiveHandler _receive; } }第一个类就是定义一些接口,和一些委托,没有实质性的东西。第二个类是定义了上一个接口类中的ToClient的事件和方法,作用之后会讲到。然后就是集成ICommand接口的实质性的数据类using System;using System.Collections.Generic;using System.Linq;using System.Text;using ICommand;namespace NetRemoting{ public class RemotingObject : MarshalByRefObject, IRemotingObject { /// <summary> /// 发送事件 /// </summary> public event SendHandler ClientToServer { add { _send += value; } remove { _send -= value; } } /// <summary> /// 接收消息事件 /// </summary> public event ReceiveHandler ServerToClient; /// <summary> /// 发送事件 /// </summary> public event UserChangedHandler Login { add { _login += value; } remove { _login -= value; } } /// <summary> /// 发送事件 /// </summary> public event UserChangedHandler Exit { add { _exit += value; } remove { _exit -= value; } } /// <summary> /// 加法运算 /// </summary> /// <param name="x1">参数1</param> /// <param name="x2">参数2</param> /// <returns></returns> public string SUM(int x1, int x2) { return x1 + "+" + x2 + "=" + (x1 + x2); } /// <summary> /// 绑定服务端向客户端发送消息的事件方法 /// </summary> /// <param name="receive">接收事件</param> public Delegate[] GetServerEventList() { return this.ServerToClient.GetInvocationList(); } /// <summary> /// 发送消息 /// </summary> /// <param name="info"></param> /// <param name="toName"></param> public void ToServer(object info, string toName) { if (_send != null) _send(info, toName); } /// <summary> /// 接收消息 /// </summary> /// <param name="info"></param> /// <param name="toName"></param> public void ToClient(object info, string toName) { if (_receive != null) _receive(info, toName); } /// <summary> /// 登录 /// </summary> /// <param name="name">用户名</param> public void ToLogin(string name) { if (!_nameHash.Contains(name)) { _nameHash.Add(name); if (_login != null) _login(name); } else { throw new Exception("用户已存在"); } } /// <summary> /// 退出 /// </summary> /// <param name="name">用户名</param> public void ToExit(string name) { if (_nameHash.Contains(name)) { _nameHash.Remove(name); if (_exit != null) _exit(name); } } private SendHandler _send; private ReceiveHandler _receive; private UserChangedHandler _login; private UserChangedHandler _exit; private HashSet<string> _nameHash = new HashSet<string>(); }}该类集成了MarshalByRefObject由于Remoting传递的对象是以引用的方式,因此所传递的远程对象类必须继承MarshalByRefObject。MSDN对MarshalByRefObject的说明是:MarshalByRefObject 是那些通过使用代理交换消息来跨越应用程序域边界进行通信的对象的基类。不是从 MarshalByRefObject 继承的对象会以隐式方式按值封送。当远程应用程序引用一个按值封送的对象时,将跨越远程处理边界传递该对象的副本。因为您希望使用代理方法而不是副本方法进行通信,因此需要继承MarshallByRefObject。该类主要是定义了一些方法用于客户端触发事件,ToServer,ToClient,ToLogin,ToExit以及一些事件,客户端发向服务端的事件,和服务端发向客户端的事件。_nameHash 只是记录有哪些用户登录了。接下去就是客户端和服务端了。首先服务端:using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Runtime.Remoting;using System.Runtime.Remoting.Channels;using System.Runtime.Remoting.Channels.Http;using NetRemoting;using System.Collections;using System.Runtime.Serialization.Formatters;using ICommand;namespace NetRemotingServer{ public partial class Server : Form { public Server() { InitializeComponent(); Initialize(); } /// <summary> /// 注册通道 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Server_Load(object sender, EventArgs e) { ChannelServices.RegisterChannel(_channel, false); //RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotingObject), "SumMessage", WellKnownObjectMode.Singleton); //a方案 /*将给定的 System.MarshalByRefObject 转换为具有指定 URI 的 System.Runtime.Remoting.ObjRef 类的实例。 ObjRef :存储生成代理以与远程对象通信所需要的所有信息。*/ ObjRef objRef = RemotingServices.Marshal(_remotingObject, "SumMessage");//b方案 _remotingObject.ClientToServer += (info, toName) => { rxtInfo.Invoke((MethodInvoker)(() => { rxtInfo.AppendText(info.ToString() + "\r\n"); })); SendToClient(info, toName); }; _remotingObject.Login += (name) => { rxtInfo.Invoke((MethodInvoker)(() => { rxtInfo.AppendText(name + " 登录" + "\r\n"); })); }; _remotingObject.Exit += (name) => { rxtInfo.Invoke((MethodInvoker)(() => { rxtInfo.AppendText(name + " 退出" + "\r\n"); })); }; } /// <summary> /// 注销通道 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Server_FormClosing(object sender, FormClosingEventArgs e) { if (_channel != null) { _channel.StopListening(null); ChannelServices.UnregisterChannel(_channel); } } /// <summary> /// 广播消息 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSend_Click(object sender, EventArgs e) { SendToClient(txtSend.Text, txtName.Text); } /// <summary> /// 发送消息到客户端 /// </summary> /// <param name="info"></param> /// <param name="toName"></param> private void SendToClient(object info, string toName) { //foreach (var v in _remotingObject.GetServerEventList()) //{ // try // { // ReceiveHandler receive = (ReceiveHandler)v; // receive.BeginInvoke(info, toName, null, null); // } // catch // { } // } _remotingObject.ToClient(txtSend.Text, txtName.Text); } /// <summary> /// 初始化 /// </summary> private void Initialize() { //设置反序列化级别 BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider(); BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider(); serverProvider.TypeFilterLevel = TypeFilterLevel.Full;//支持所有类型的反序列化,级别很高 IDictionary idic = new Dictionary<string, string>(); idic["name"] = "serverHttp"; idic["port"] = "8022"; _channel = new HttpChannel(idic, clientProvider, serverProvider); _remotingObject = new RemotingObject(); } HttpChannel _channel; private RemotingObject _remotingObject; }}然后客户端:using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Runtime.Remoting;using System.Runtime.Remoting.Channels;using System.Runtime.Remoting.Channels.Http;using ICommand;using System.Runtime.Serialization.Formatters;using System.Collections;namespace NetRemotingClient{ public partial class Client : Form { public Client() { InitializeComponent(); } /// <summary> /// 注册通道 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Client_Load(object sender, EventArgs e) { try { //设置反序列化级别 BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider(); BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider(); serverProvider.TypeFilterLevel = TypeFilterLevel.Full;//支持所有类型的反序列化,级别很高 //信道端口 IDictionary idic = new Dictionary<string, string>(); idic["name"] = "clientHttp"; idic["port"] = "0"; HttpChannel channel = new HttpChannel(idic, clientProvider, serverProvider); ChannelServices.RegisterChannel(channel, false); _remotingObject = (IRemotingObject)Activator.GetObject(typeof(IRemotingObject), "http://localhost:8022/SumMessage"); //_remotingObject.ServerToClient += (info, toName) => { rtxMessage.AppendText(info + "\r\n"); }; SwapObject swap = new SwapObject(); _remotingObject.ServerToClient += swap.ToClient; swap.SwapServerToClient += (info, toName) => { rtxMessage.Invoke((MethodInvoker)(() => { if (toName == txtLogin.Text || toName == "") rtxMessage.AppendText(info + "\r\n"); })); }; } catch (Exception ex) { MessageBox.Show(ex.Message); } } /// <summary> /// 登录 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnLogin_Click(object sender, EventArgs e) { try { if (txtLogin.Text == "") throw new Exception("用户名不得为空"); _remotingObject.ToLogin(txtLogin.Text); } catch (Exception ex) { MessageBox.Show(ex.Message); } } /// <summary> /// 退出 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Client_FormClosing(object sender, FormClosingEventArgs e) { try { _remotingObject.ToExit(txtLogin.Text); } catch { } } /// <summary> /// 发送 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSend_Click(object sender, EventArgs e) { //rtxMessage.AppendText(_remotingObject.SUM(2, 4) + "\r\n"); _remotingObject.ToServer(txtSend.Text, txtName.Text); } private IRemotingObject _remotingObject; }}服务端实现步骤:1、注册通道要跨越应用程序域进行通信,必须实现通道。如前所述,Remoting提供了IChannel接口,分别包含TcpChannel和HttpChannel两种类型的通道。这两种类型除了性能和序列化数据的格式不同外,实现的方式完全一致,因此下面我们就以TcpChannel为例。注册TcpChannel,首先要在项目中添加引用“System.Runtime.Remoting”,然后using名字空间:System.Runtime.Remoting.Channel.Tcp。代码如下:TcpChannel channel = new TcpChannel(8022);ChannelServices.RegisterChannel(channel);在实例化通道对象时,将端口号作为参数传递。然后再调用静态方法RegisterChannel()来注册该通道对象即可。2、注册远程对象注册了通道后,要能激活远程对象,必须在通道中注册该对象。根据激活模式的不同,注册对象的方法也不同。(1) SingleTon模式对于WellKnown对象,可以通过静态方法RemotingConfiguration.RegisterWellKnownServiceType()来实现:RemotingConfiguration.RegisterWellKnownServiceType( typeof(ServerRemoteObject.ServerObject), "ServiceMessage",WellKnownObjectMode.SingleTon);(2)SingleCall模式注册对象的方法基本上和SingleTon模式相同,只需要将枚举参数WellKnownObjectMode改为SingleCall就可以了。RemotingConfiguration.RegisterWellKnownServiceType( typeof(ServerRemoteObject.ServerObject), "ServiceMessage",WellKnownObjectMode.SingleCall);客户端实现步骤:1、注册通道:TcpChannel channel = new TcpChannel();ChannelServices.RegisterChannel(channel);注意在客户端实例化通道时,是调用的默认构造函数,即没有传递端口号。事实上,这个端口号是缺一不可的,只不过它的指定被放在后面作为了Uri的一部分。2、获得远程对象。与服务器端相同,不同的激活模式决定了客户端的实现方式也将不同。不过这个区别仅仅是WellKnown激活模式和客户端激活模式之间的区别,而对于SingleTon和SingleCall模式,客户端的实现完全相同。(1) WellKnown激活模式要获得服务器端的知名远程对象,可通过Activator进程的GetObject()方法来获得:ServerRemoteObject.ServerObject serverObj = (ServerRemoteObject.ServerObject)Activator.GetObject( typeof(ServerRemoteObject.ServerObject), "tcp://localhost:8080/ServiceMessage");首先以WellKnown模式激活,客户端获得对象的方法是使用GetObject()。其中参数第一个是远程对象的类型。第二个参数就是服务器端的uri。如果是http通道,自然是用http://localhost:8022/ServiceMessage了。因为我是用本地机,所以这里是localhost,你可以用具体的服务器IP地址来代替它。端口必须和服务器端的端口一致。后面则是服务器定义的远程对象服务名,即ApplicationName属性的内容。//设置反序列化级别 BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider(); BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider(); serverProvider.TypeFilterLevel = TypeFilterLevel.Full;//支持所有类型的反序列化,级别很高 //信道端口 IDictionary idic = new Dictionary<string, string>(); idic["name"] = "clientHttp"; idic["port"] = "0"; HttpChannel channel = new HttpChannel(idic, clientProvider, serverProvider);从上述代码中可以看到注册方式有所变化,那是因为客户端注册服务端的事件时会报错“不允许类型反序列化”。还有一个需要注意的是:ObjRef objRef = RemotingServices.Marshal(_remotingObject, "SumMessage");//RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotingObject), "SumMessage", WellKnownObjectMode.Singleton);//调用系统自动创建,导致拿不到_remotingObject对象的实例化,这样后期绑定事件就无法操作下去了,当然也可以直接静态事件绑定,这样就不需要手动实例化对象了通过该方法手动创建_remotingObject这个对象的实例化。然后之前讲到了一个SwapObject这个类,这个类的作用是事件交换。 _remotingObject.ServerToClient +=方法();//这样因为这个方法是客户端的,服务端无法调用,所以需要一个中间转换的 SwapObject swap = new SwapObject();//先创建一个Swap对象 _remotingObject.ServerToClient += swap.ToClient;//然后服务端事件发信息给swap,然后swap再通过事件发消息给客户端,swap是客户端创建的所以可以发送,而swap是服务端的类,所以服务端也能识别,swap起到了中间过渡的作用 swap.SwapServerToClient +=方法();以上是两天.Net Remoting的学习结果。最后附上源码:NetRemoting_jb51.rar以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

序列化对象为字节数组复制代码 代码如下:using System.IO;using System.Runtime.Serialization.Formatters.Binary;        protected byte[] Serialize<T>(T t)        {            MemoryStream mStream = new MemoryStream();            BinaryFormatter bFormatter = new BinaryFormatter();            bFormatter.Serialize(mStream, t);            return mStream.GetBuffer();        }反序列化字节数组为对象复制代码 代码如下:

复制代码 代码如下:/// <summary>        /// 删除掉空文件夹        /// 所有没有子“文件系统”的都将被删除        /// </summary>        /// <param name="storagepath"></param>        public static void KillEmptyDirectory(String storagepath)        {            DirectoryInfo dir = new DirectoryInfo(storagepath);            DirectoryInfo[] subdirs = dir.GetDirectories("*.*",

你可能在上篇文章中《深入多线程之:双向信号与竞赛的用法分析》注意到了这个模式:两个Waiting 循环都要下面的构造:复制代码 代码如下:lock(_locker){        while(!_flag) Monitor.Wait(_locker);        _flag = false;}在这里_flag被另一线程设置为true。这是,从作用上讲,这里在模仿AutoResetEvent。如果我们将 _flag = false;去掉,那么我们就得到了一个基本的ManualResetEvent.让我们使用Wait和Pulse来为ManualResetEvent完成剩余的代码吧。复制代码 代码如下:readonly object _locker = new object();        bool _signal;        void WaitOne()        {            lock (_locker)            {                while (!_signal) Monitor.Wait(_locker);            }        }        void Set()        {            lock (_locker) { _signal = true; Monitor.PulseAll(_locker); }        }        void Reset() { lock (_locker) _signal = false; }在这里使用PulseAll,是因为可能有很多阻塞的线程。如果在WaitOne方法中增加_signal=false就可以简单的模拟AutoResetEvent.例如:复制代码 代码如下:void WaitOne()        {            lock (_locker)            {                while (!_signal) Monitor.Wait(_locker);                _signal = false; //实现自动关闭功|能            }        }然后在Set方法中,将PulseAll修改为PulseLock(_locker) {_signal = true; Monitor.Pulse(_locker);}如果使用的是int类型的_signal 标志,那么我们可以得到一个最基本的Semaphore.Waiting Queues and PulseAll当多余一个线程在同一个对象上面等待的时候,一个 “等待队列(waiting queue)” 就形成了。每一次调用Pulse都会释放在”等待队列”头部的一个线程。下面的图形象的展示了这一点: 线程调用Monitor.Enter 进入ReadyQueue. 等待获取锁,成功获取锁后,如果正常的执行,那么之后会调用Monitor.Exit退出,否则如果获取了锁之后发现需要等待其他的线程或者是其他阻塞条件,那么调用Wait方法,就进入了等待队列,当等待的线程完成并调用Pulse后,处在WaitingQueue头部的线程就被 Pulse了,等待CPU调度 。之后再次进入Ready Queue,重新获取锁。Countdown借助Wait和Pulse,我们可以实现CountdownEvent的主要功能。例如:复制代码 代码如下:class Countdown    {        object _locker = new object();        int _value; //使用_value来计数        public Countdown() { }        public Countdown(int initialCount) { _value = initialCount; }        public void Singnal() { AddCount(-1); } //将计数减一        public void AddCount(int amount)        {            lock (_locker)            {                _value += amount; //将计数增加或减少                if (_value <= 0) Monitor.PulseAll(_locker);//如果value<=0,说明所有等待的任务都完成了。            }        }        public void Wait()        {            lock (_locker)            {                //只要计数 > 0 就等待。                while (_value > 0)                {                    Monitor.Wait(_locker);                }            }        }}这和我们上次的代码几乎一致,只是这次我们的阻塞条件基于一个整型_value标志。

焦点访谈

最新最热的文章

更多 >

COPYRIGHT (©) 2017 Copyright ©2017 365体育在线备用网址 网站地图

联系我们

827570882

扫描二维码分享到微信