C#难题,知识面广的朋友帮忙进来看一下!!

weizhuangwen 2013-11-22 07:50:58
说明:
是这样的,我想做一个窗体程序,并且是一直运行于内存中的,这个窗体程序提供文件转换服务(JPG转TIF)。
但这个窗体自身并不包含业务,而业务逻辑可能在其他N个进程中处理。这些进程处理到需要转换文件的时候,就把文件路径发送到这个窗体程序中,这个窗体程序转换好后,通知发送过来的进程(“已经转换好了”)。然后这个进程继续处理它自己的业务逻辑。(重点提示:这样的业务进程可能有N多条)

-------------------------------------------
问题是:我这个窗体应该用什么技术来提供与其它进程进行通讯呢??
-------------------------------------------
我的思考:我原先想用TCP/IP端口通讯,但觉得在本机运行的程序还要用到网络通讯的方式,有点不合理。然后我想到内存共享,但又不好管理,要写大量正则。接着我想到windows消息队列组件,但依赖于组件,又怕不稳定,而且内部运行机制不透明(并且还要安装)。然后我又想到web service,但它却不能提供UI界面。然后我又想到窗体间的回调函数(目前觉得最好是这个)。
...全文
586 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
木子李1212 2013-11-24
  • 打赏
  • 举报
回复
用wcf吧,很强大的,可以实现
weizhuangwen 2013-11-24
  • 打赏
  • 举报
回复
引用 16 楼 bf6543 的回复:
进程间通讯,其实用SendMessage就可以实现,刚找了一下以前做的东西,正好是进程间通讯的,主要是主程序调用校验程序,校验程序返回校验结果。

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace SendMsg
{
    #region 结构体定义
    [StructLayout(LayoutKind.Sequential)]
    public struct COPYDATASTRUCT
    {
        public int dwData;
        public int cbData;
        public int lpData;
    }

    //定义要传递的Struct
    [StructLayout(LayoutKind.Sequential)]
    struct SendMsgInfo
    {
        /// <summary>
        /// 参数(单号)
        /// </summary>
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
        public string AccessionNum;
        /// <summary>
        /// 参数(原文)
        /// </summary>
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5000)]
        public string ReportTxt;
        /// <summary>
        /// 参数(Ris用户)
        /// </summary>
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
        public string RisUid;
        /// <summary>
        /// 调用方法名
        /// </summary>
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
        public string FunctionNum;
        /// <summary>
        /// 端口
        /// </summary>
        public int Handle;
        /// <summary>
        /// 返回值
        /// </summary>
        public bool Result;
        /// <summary>
        /// Err信息
        /// </summary>
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 200)]
        public string ResultMsg;
    }
    #endregion

    class CaSendMsg
    {
        Process pro;
        const int WM_COPYDATA = 0x004A;

        private string _winFrmName = @"校验程序";
        private string _path = @"校验.exe";
        private int _interval = 500;
        private int _maxTimes = 5;

        /// <summary>
        /// 窗体名称
        /// </summary>
        public string WinFrmName
        {
            set { _winFrmName = value; }
            get { return _winFrmName; }
        }

        /// <summary>
        /// 程序路径
        /// </summary>
        public string Path
        {
            set { _path = value; }
            get { return _path; }
        }

        /// <summary>
        /// 等待轮序频率 秒/次
        /// </summary>
        public int Interval
        {
            set { _interval = value; }
            get { return _interval; }
        }

        /// <summary>
        /// 上限次数
        /// </summary>
        public int MaxTimes
        {
            set { _maxTimes = value; }
            get { return _maxTimes; }
        }

        [DllImport("user32", EntryPoint = "SendMessageA")]
        public static extern int SendMessage(int hWnd, int wMsg, int wParam, ref COPYDATASTRUCT lParam);
        
        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        public static extern int FindWindow(string lpClassName, string
            lpWindowName);        

        /// <summary>
        /// ca校验
        /// </summary>
        /// <param name="h"></param>
        /// <returns></returns>
        public bool CACheck(SendMsgInfo h)
        {
            int hWnd = GetWinFrmHwnd();
            if (hWnd <= 0)
                return false;
            return CACheck(h, hWnd);
        }

        /// <summary>
        /// 获取程序句柄
        /// </summary>
        /// <returns></returns>
        private int GetWinFrmHwnd()
        {
            int hWnd = FindWindow(null, _winFrmName);
            if (hWnd <= 0)
            {
                hWnd = StartNewPro(_path);
            }
            return hWnd;
        }

        /// <summary>
        /// 开启新的校验进程
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        private int StartNewPro(string path)
        {
            try
            {
                pro = new Process();
                pro.StartInfo.FileName = path;
                pro.Start();
                return pro.MainWindowHandle.ToInt32();
            }
            catch
            {
                return 0;
            }
        }

        public bool CACheck(SendMsgInfo info, int hWnd)
        {
            try
            {
                int size = Marshal.SizeOf(typeof(SendMsgInfo));
                byte[] Bytes = new byte[size];
                //根据定义的尺寸分配内存块
                GCHandle GC = GCHandle.Alloc(Bytes, GCHandleType.Pinned);
                IntPtr ptr1 = GC.AddrOfPinnedObject();
                //获得Struct对应的IntPtr
                Marshal.StructureToPtr(info, ptr1, false);
                COPYDATASTRUCT SendData = new COPYDATASTRUCT();
                SendData.lpData = ptr1.ToInt32();
                SendData.cbData = size;
                
                if (hWnd > 0)
                {
                    SendMessage(hWnd, WM_COPYDATA, 0, ref (SendData));
                }

                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool getCaResult(System.Windows.Forms.Message m)
        {
            COPYDATASTRUCT RecvData = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
            SendMsgInfo info = (SendMsgInfo)Marshal.PtrToStructure((IntPtr)RecvData.lpData, typeof(SendMsgInfo));
            //h.ResultMsg;
            return info.Result;
        }

    }
}
调用:

//接收消息
protected override void DefWndProc(ref System.Windows.Forms.Message m)
        {
            switch (m.Msg)
            {
                case WM_COPYDATA:
                    COPYDATASTRUCT RecvData = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
                    SendMsgInfo h = (SendMsgInfo)Marshal.PtrToStructure((IntPtr)RecvData.lpData, typeof(SendMsgInfo));
                   
            //返回校验结果
            SendMsgInfo returnInfo = new SendMsgInfo();
            returnInfo.Handle = h.Handle;
            returnInfo.AccessionNum = h.AccessionNum;
            returnInfo.Result = result;
            returnInfo.ResultMsg = "";
            CaSendMsg c = new CaSendMsg();
            c.CACheck(returnInfo, returnInfo.Handle);
                default:
                    base.DefWndProc(ref m);
                    break;
            }
        }
谢谢了啊,你的代码功力很深厚,在GetLParam处还用了结构体。涉及到的理论比较深,要好好研究一下才行。再次谢谢
weizhuangwen 2013-11-24
  • 打赏
  • 举报
回复
引用 14 楼 dk385 的回复:
用SendMessage/postmessage 就能达到要求。 业务进程通过SendMessage/postmessage 发送消息到转换进程,考虑到并发能力,转换进程可以在线程中去处理文件转换, 转换完了再通过SendMessage/postmessage通知业务进程。
是啊,我也觉得这种方式可以。就想问问大家知识面广的朋友,没有更加好的。既然没有的话,那么我就采用SendMessage来通信,谢谢大家了。
rainychan2009 2013-11-23
  • 打赏
  • 举报
回复
如果要我实现,我就把 转文件的功能做成一个子进程A 业务子进程需要的时候就调用,A结束也就是活干完了。
  • 打赏
  • 举报
回复
太乱了,而且你说你什么都会,什么都不想写,我真是佩服了。我建议你先用任何一种你懂的东西做出来一个,再说。 使用udp对本机(127.0.0.1)进行一次“一问一答”的短链接访问是不错的选择。
xloveme 2013-11-23
  • 打赏
  • 举报
回复
看你的需求,转移程序根本就不需要窗口。 可以做为控制台程序,然后其他应用程序与它管道通信。
bu_ge 2013-11-23
  • 打赏
  • 举报
回复
以上都是校验程序的,主程序的代码不好摘,不过同样调用CaSendMsg
bu_ge 2013-11-23
  • 打赏
  • 举报
回复
进程间通讯,其实用SendMessage就可以实现,刚找了一下以前做的东西,正好是进程间通讯的,主要是主程序调用校验程序,校验程序返回校验结果。

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace SendMsg
{
    #region 结构体定义
    [StructLayout(LayoutKind.Sequential)]
    public struct COPYDATASTRUCT
    {
        public int dwData;
        public int cbData;
        public int lpData;
    }

    //定义要传递的Struct
    [StructLayout(LayoutKind.Sequential)]
    struct SendMsgInfo
    {
        /// <summary>
        /// 参数(单号)
        /// </summary>
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
        public string AccessionNum;
        /// <summary>
        /// 参数(原文)
        /// </summary>
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5000)]
        public string ReportTxt;
        /// <summary>
        /// 参数(Ris用户)
        /// </summary>
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
        public string RisUid;
        /// <summary>
        /// 调用方法名
        /// </summary>
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
        public string FunctionNum;
        /// <summary>
        /// 端口
        /// </summary>
        public int Handle;
        /// <summary>
        /// 返回值
        /// </summary>
        public bool Result;
        /// <summary>
        /// Err信息
        /// </summary>
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 200)]
        public string ResultMsg;
    }
    #endregion

    class CaSendMsg
    {
        Process pro;
        const int WM_COPYDATA = 0x004A;

        private string _winFrmName = @"校验程序";
        private string _path = @"校验.exe";
        private int _interval = 500;
        private int _maxTimes = 5;

        /// <summary>
        /// 窗体名称
        /// </summary>
        public string WinFrmName
        {
            set { _winFrmName = value; }
            get { return _winFrmName; }
        }

        /// <summary>
        /// 程序路径
        /// </summary>
        public string Path
        {
            set { _path = value; }
            get { return _path; }
        }

        /// <summary>
        /// 等待轮序频率 秒/次
        /// </summary>
        public int Interval
        {
            set { _interval = value; }
            get { return _interval; }
        }

        /// <summary>
        /// 上限次数
        /// </summary>
        public int MaxTimes
        {
            set { _maxTimes = value; }
            get { return _maxTimes; }
        }

        [DllImport("user32", EntryPoint = "SendMessageA")]
        public static extern int SendMessage(int hWnd, int wMsg, int wParam, ref COPYDATASTRUCT lParam);
        
        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        public static extern int FindWindow(string lpClassName, string
            lpWindowName);        

        /// <summary>
        /// ca校验
        /// </summary>
        /// <param name="h"></param>
        /// <returns></returns>
        public bool CACheck(SendMsgInfo h)
        {
            int hWnd = GetWinFrmHwnd();
            if (hWnd <= 0)
                return false;
            return CACheck(h, hWnd);
        }

        /// <summary>
        /// 获取程序句柄
        /// </summary>
        /// <returns></returns>
        private int GetWinFrmHwnd()
        {
            int hWnd = FindWindow(null, _winFrmName);
            if (hWnd <= 0)
            {
                hWnd = StartNewPro(_path);
            }
            return hWnd;
        }

        /// <summary>
        /// 开启新的校验进程
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        private int StartNewPro(string path)
        {
            try
            {
                pro = new Process();
                pro.StartInfo.FileName = path;
                pro.Start();
                return pro.MainWindowHandle.ToInt32();
            }
            catch
            {
                return 0;
            }
        }

        public bool CACheck(SendMsgInfo info, int hWnd)
        {
            try
            {
                int size = Marshal.SizeOf(typeof(SendMsgInfo));
                byte[] Bytes = new byte[size];
                //根据定义的尺寸分配内存块
                GCHandle GC = GCHandle.Alloc(Bytes, GCHandleType.Pinned);
                IntPtr ptr1 = GC.AddrOfPinnedObject();
                //获得Struct对应的IntPtr
                Marshal.StructureToPtr(info, ptr1, false);
                COPYDATASTRUCT SendData = new COPYDATASTRUCT();
                SendData.lpData = ptr1.ToInt32();
                SendData.cbData = size;
                
                if (hWnd > 0)
                {
                    SendMessage(hWnd, WM_COPYDATA, 0, ref (SendData));
                }

                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool getCaResult(System.Windows.Forms.Message m)
        {
            COPYDATASTRUCT RecvData = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
            SendMsgInfo info = (SendMsgInfo)Marshal.PtrToStructure((IntPtr)RecvData.lpData, typeof(SendMsgInfo));
            //h.ResultMsg;
            return info.Result;
        }

    }
}
调用:

//接收消息
protected override void DefWndProc(ref System.Windows.Forms.Message m)
        {
            switch (m.Msg)
            {
                case WM_COPYDATA:
                    COPYDATASTRUCT RecvData = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
                    SendMsgInfo h = (SendMsgInfo)Marshal.PtrToStructure((IntPtr)RecvData.lpData, typeof(SendMsgInfo));
                   
            //返回校验结果
            SendMsgInfo returnInfo = new SendMsgInfo();
            returnInfo.Handle = h.Handle;
            returnInfo.AccessionNum = h.AccessionNum;
            returnInfo.Result = result;
            returnInfo.ResultMsg = "";
            CaSendMsg c = new CaSendMsg();
            c.CACheck(returnInfo, returnInfo.Handle);
                default:
                    base.DefWndProc(ref m);
                    break;
            }
        }
Todd_Pointer 2013-11-23
  • 打赏
  • 举报
回复
我会首选UDP,省心省力,性能也不太是问题。 如果你对Win32有了解, 知道windows消息机制、窗口句柄什么的也, 也可以通过PostMessage来做。 另外Mailslots也不错,但貌似也是要调用Win32 API,印象中.net framework没这个功能,否则也比较合用。 内存共享没什么必要,你这个交互的数据量不大。 像Pipe的话比较适合一对一,你这个一对多就比较麻烦。 WCF、RPC个人觉得重了。
秋的红果实 2013-11-23
  • 打赏
  • 举报
回复
没弄过这种的,帮顶一个
threenewbee 2013-11-23
  • 打赏
  • 举报
回复
引用 6 楼 weizhuangwen 的回复:
[quote=引用 2 楼 caozhy 的回复:] 用wcf嘛。
这个不行哦,一定要是winform的[/quote] wcf可以用在winform中啊。
weizhuangwen 2013-11-23
  • 打赏
  • 举报
回复
引用 3 楼 emailtome 的回复:
The following IPC mechanisms are supported by Windows: Clipboard COM Data Copy DDE File Mapping Mailslots Pipes RPC Windows Sockets
没看懂啊哥们,能不能配上点中文说明啊
weizhuangwen 2013-11-23
  • 打赏
  • 举报
回复
引用 4 楼 wind_cloud2011 的回复:
可不可以通过中间的数据库?一些处理信息写入数据,前端通过数据库取信息,
不也行哦。
weizhuangwen 2013-11-23
  • 打赏
  • 举报
回复
引用 2 楼 caozhy 的回复:
用wcf嘛。
这个不行哦,一定要是winform的
wind_cloud2011 2013-11-23
  • 打赏
  • 举报
回复
可不可以通过中间的数据库?一些处理信息写入数据,前端通过数据库取信息,
大飞飞虫 2013-11-23
  • 打赏
  • 举报
回复
看来你的问题不是100分这么简单,不如花RMB直接请人搞吧。
家鸣 2013-11-23
  • 打赏
  • 举报
回复
用SendMessage/postmessage 就能达到要求。 业务进程通过SendMessage/postmessage 发送消息到转换进程,考虑到并发能力,转换进程可以在线程中去处理文件转换, 转换完了再通过SendMessage/postmessage通知业务进程。
emailtome 2013-11-22
  • 打赏
  • 举报
回复
The following IPC mechanisms are supported by Windows: Clipboard COM Data Copy DDE File Mapping Mailslots Pipes RPC Windows Sockets
threenewbee 2013-11-22
  • 打赏
  • 举报
回复
用wcf嘛。
weizhuangwen 2013-11-22
  • 打赏
  • 举报
回复
已经想了好久了,朋友们帮帮忙。一个窗体程序,除了我上面说到的,还提供有什么通讯接口呢?

110,537

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧