gpt4 book ai didi

c#进程之间对象传递方法

转载 作者:qq735679552 更新时间:2022-09-27 22:32:09 26 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章c#进程之间对象传递方法由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

1. 起源 。

kv项目下载底层重构升级决定采用独立进程进行media下载处理,以能做到模块复用之目的,因此涉及到了独立进程间的数据传递问题.

目前进程间数据传递,多用wm_copydata、共享dll、内存映射、remoting等方式。相对来说,wm_copydata方式更为简便,网上更到处是其使用方法.

而且marshal这个静态类,其内置多种方法,可以很方便实现字符串、结构体等数据在不同进程间传递.

那么,对象呢?如何传递?

2、序列化 。

想到了,newtonsoft.json.dll这个神器。相对于内建的xmlserializer这个东西,我更喜欢用json.

那么,如此处理吧,我们来建个demo解决方案,里面有hostapp、clildapp两个项目,以做数据传递.

3、childapp项目 。

先说这个,我没有抽取共用的数据单独出来,而做为demo,直接写入此项目中,hostapp引用此项目,就可引用其中public出来的数据类型.

数据结构部分代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
[structlayout(layoutkind.sequential)]
  public struct copydatastruct
  {
   public intptr dwdata;
   public int cbdata;
   [marshalas(unmanagedtype.lpstr)]
   public string lpdata;
  }
  [serializable]
  public class person
  {
   private string name;
   private int age;
   private list<person> children;
   public person( string name, int age)
   {
    this .name = name;
    this .age = age;
    this .children = new list<person>();
   }
   public string name
   {
    get { return this .name; }
    set { this .name = value; }
   }
   public int age
   {
    get { return this .age; }
    set { this .age = value; }
   }
   public list<person> children
   {
    get { return this .children; }
   }
   public void addchildren()
   {
    this .children.add( new person( "liuxm" , 9));
    this .children.add( new person( "liuhm" , 7));
   }
   public override string tostring()
   {
    string info = string .format( "姓名:{0},年龄:{1}" , this .name, this .age);
    if ( this .children.count != 0)
    {
     info += ( this .children.count == 1) ? "\r\n孩子:" : "\r\n孩子们:" ;
     foreach (var child in this .children)
      info += "\r\n" + child.tostring();
    }
    return info;
   }
  }

窗体代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public partial class childform : form
  {
   public const int wm_copydata = 0x004a;
   private intptr hosthandle = intptr.zero;
   person person = new person( "liujw" , 1999);
   [dllimport( "user32.dll" , entrypoint = "sendmessage" )]
   private static extern int sendmessage(
    intptr hwnd,    // handle to destination window
    int msg,     // message
    int wparam,    // first message parameter
    ref copydatastruct lparam // second message parameter
   );
   public childform( string [] args)
   {
    initializecomponent();
    if (args.length != 0)
     this .hosthandle = (intptr) int .parse(args[0]);
   }
   private void btnsubmit_click( object sender, eventargs e)
   {
    this .person.name = txtname.text;
    int age;
    this .person.age = int .tryparse(txtage.text, out age) ? age : 0;
    this .person.addchildren();
    if ( this .hosthandle != intptr.zero)
    {
     string data = getpersionstr();
     copydatastruct cds = new copydatastruct();
     cds.dwdata = (intptr)901;
     cds.cbdata = data.length + 1;
     cds.lpdata = data;
     sendmessage( this .hosthandle, wm_copydata, 0, ref cds);
    }
   }
   private string getpersionstr()
   {
    return jsonconvert.serializeobject( this .person);
   }
  }

这样在窗体按钮btnsubmit_click事件中,完成了数据向hostapp的字符串形式传递.

如何获取宿主程序的窗口句柄呢?改造下childapp的program.cs过程即可:

?
1
2
3
4
5
6
7
8
9
10
/// <summary>
   /// 应用程序的主入口点。
   /// </summary>
   [stathread]
   static void main( string [] args)
   {
    application.enablevisualstyles();
    application.setcompatibletextrenderingdefault( false );
    application.run( new childform(args));
   }

3、hostapp项目 。

我们权且称之为宿主项目吧,其窗体代码为:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public partial class mainform : form
  {
   public const int wm_copydata = 0x004a;
   public mainform()
   {
    initializecomponent();
   }
   protected override void wndproc( ref message m)
   {
    base .wndproc( ref m);
    switch (m.msg)
    {
     case wm_copydata:
      copydatastruct copydata = new copydatastruct();
      type type = copydata.gettype();
      copydata = (copydatastruct)m.getlparam(type);
      string data = copydata.lpdata;
      restoreperson(data);
      break ;
    }
   }
   private void restoreperson( string data)
   {
    var person = jsonconvert.deserializeobject<person>(data);
    if (person != null )
     txtinfo.text = person.tostring();
   }
   private void btnsubmit_click( object sender, eventargs e)
   {
    runchildprocess();
   }
   private void runchildprocess()
   {
    string apppath = path.getdirectoryname(application.executablepath);
    string childpath = path.combine(apppath, "childapp.exe" );
    process.start(childpath, this .handle.tostring());
   }
  }

它的作用就是接收子进程传递回来的字串,用jsonconvert反序列化为person对象.

是不是很简单呢?

其实就是用了wm_copydata的字符串传递功能,加上json的序列化、反序列化,而实现c#不同进程间的对象传递 。

4、效果图:

c#进程之间对象传递方法

5、2017-03-24追加:

今天又发现用json序列化较为复杂的字串时,出现转义错误,导致反序列化失败。于时改用二进制序列化,转其为base64字串进行传递,问题解决.

代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public static class serializehelper
  {
   /// <summary>
   /// 序列obj对象为base64字串
   /// </summary>
   /// <param name="obj"></param>
   /// <returns></returns>
   public static string serialize( object obj)
   {
    if (obj == null )
     return string .empty;
    try
    {
     var formatter = new binaryformatter();
     var stream = new memorystream();
     formatter.serialize(stream, obj);
     stream.position = 0;
     byte [] buffer = new byte [stream.length];
     stream.read(buffer, 0, buffer.length);
     stream.close();
     return convert.tobase64string(buffer);
    }
    catch (exception ex)
    {
     throw new exception( string .format( "序列化{0}失败,原因:{1}" , obj, ex.message));
    }
   }
   /// <summary>
   /// 反序列化字符串到对象
   /// </summary>
   /// <param name="str">要转换为对象的字符串</param>
   /// <returns>反序列化出来的对象</returns>
   public static t deserialize<t>( string str)
   {
    var obj = default (t);
    if ( string .isnullorempty(str))
     return obj;
    try
    {
     var formatter = new binaryformatter();
     byte [] buffer = convert.frombase64string(str);
     memorystream stream = new memorystream(buffer);
     obj = (t)formatter.deserialize(stream);
     stream.close();
    }
    catch (exception ex)
    {
     throw new exception( string .format( "序列化{0}失败,原因:{1}" , obj, ex.message));
    }
    return obj;
   }
  }

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持我! 。

原文链接:http://www.cnblogs.com/crwy/p/6568871.html 。

最后此篇关于c#进程之间对象传递方法的文章就讲到这里了,如果你想了解更多关于c#进程之间对象传递方法的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com