国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

c#進程之間對象傳遞方法

2019-10-29 21:11:45
字體:
來源:轉載
供稿:網友

1. 起源

KV項目下載底層重構升級決定采用獨立進程進行Media下載處理,以能做到模塊復用之目的,因此涉及到了獨立進程間的數據傳遞問題。

目前進程間數據傳遞,多用WM_COPYDATA、共享dll、內存映射、Remoting等方式。相對來說,WM_COPYDATA方式更為簡便,網上更到處是其使用方法。

而且Marshal這個靜態類,其內置多種方法,可以很方便實現字符串、結構體等數據在不同進程間傳遞。

那么,對象呢?如何傳遞?

2、序列化

想到了,Newtonsoft.Json.dll這個神器。相對于內建的XmlSerializer這個東西,我更喜歡用Json。

那么,如此處理吧,我們來建個Demo解決方案,里面有HostApp、ClildApp兩個項目,以做數據傳遞。

3、ChildApp項目

先說這個,我沒有抽取共用的數據單獨出來,而做為Demo,直接寫入此項目中,HostApp引用此項目,就可引用其中public出來的數據類型。

數據結構部分代碼:

[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;  } }

窗體代碼:

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過程即可:

/// <summary>  /// 應用程序的主入口點。  /// </summary>  [STAThread]  static void Main(string[] args)  {   Application.EnableVisualStyles();   Application.SetCompatibleTextRenderingDefault(false);   Application.Run(new ChildForm(args));  }

3、HostApp項目

我們權且稱之為宿主項目吧,其窗體代碼為:

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字串進行傳遞,問題解決。

代碼如下:

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

以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持VEVB武林網!


注:相關教程知識閱讀請移步到c#教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 临邑县| 清水县| 资阳市| 安宁市| 寿阳县| 克什克腾旗| 乌鲁木齐市| 沛县| 忻州市| 雅安市| 古浪县| 芒康县| 阿勒泰市| 静宁县| 绩溪县| 万荣县| 潮安县| 砀山县| 定州市| 泸水县| 长宁县| 肥西县| 巫山县| 屯留县| 庄浪县| 宁夏| 日喀则市| 三江| 文安县| 郧西县| 望城县| 象州县| 南充市| 涟源市| 怀集县| 乐东| 正定县| 崇义县| 东兴市| 梁山县| 靖西县|