討論區快速選單
知識庫快速選單
網路投保旅行平安險 討論區最近新進100則主題 傑米的攝影旅遊筆記
[ 回上頁 ] [ 討論區發言規則 ]
關於DLL檔要如何共享記憶體或資料
更改我的閱讀文章字型大小
作者 : love007002(爆走笨魚)
[ 貼文 35 | 人氣 1891 | 評價 0 | 評價/貼文 0 | 送出評價 3 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2015/10/27 下午 03:58:07
我可以請問各位, 如果有一隻C# DLL檔, A跟B視窗主程式中, 各載入同一個DLL檔後, DLL檔是自行編譯的從PLC資料複製一份ArrayList(宣告成private 靜態變數)的資料格式,但兩隻主程式執行後, 我發現這兩隻的ArrayList資料卻不共享.
這要怎麼做才能達到同一份資料做讀寫動作?

以下是我的DLL檔. Process A 與 B個別載入這隻DLL, A主程式是有包含PLC元件, 所以它將會呼叫建立所有PLC資料, A與B可以對這些PLC內容作讀寫.
但我發現當A跟B執行時, DLL的資料是個別獨立的~要怎麼做才能達到各別不同執行程式可共享同那些資料區塊...
拜託各位可以幫我解答~是否有人可以提供範本或程式給我, 謝謝.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using E_PlcModule;
using System.Net.Sockets;

namespace ShareData
{
    public class ShareData
    {
     private static ArrayList PLCDataTemp = new ArrayList(); //PLC資料暫存
     private static ArrayList PLCData = new ArrayList();//實際PLC資料
     private static ArrayList PLCObject = new ArrayList();//PLC的元物件
     private static ShareData myclass = new ShareData();

     public static void setPLCDataBlock(string[,] arraydata)
     {

     if (PLCDataTemp.Count > 0)
     {
     myclass.findRepeatPLCData(PLCDataTemp, arraydata);
     }
     else
     {
     PLCDataTemp.Add(arraydata);
     }

     PLCData = PLCDataTemp;
     }

     public static String getPLCDataBlock(String Addr)
     {
     for (int i = 0; i < PLCObject.Count; i++)
     {
     object PlcObject = PLCObject[i];

     if (!((E_PlcModule.E_PlcModule)PlcObject).ConnectStatus)
     {
     PLCDataTemp.Clear();
     return "";
     }
     }

     if (PLCData.Count > 0)
     {
     for (int blackNum = 0; blackNum < PLCData.Count; blackNum++)
     {
     String[,] temp = (string[,])PLCData[blackNum];
     for (int i = 0; i < temp.GetLength(0); i++)
     {
     if (temp[i, 0] == (Addr.ToUpper()))
     {
     return temp[i, 1];
     }
     }
     }
     }
    

     return "";
     }

     private void findRepeatPLCData(ArrayList Data, string[,] sourceArrayData)
     {
     int DeleteArraylistCount = 0;
     bool find = false;

     for (int Index = 0; Index < Data.Count; Index++)
     {
     String[,] temp = (string[,]) Data[Index];
     for (int i = 0; i < temp.GetLength(0); i++)
     {
     if (temp[i, 0] == sourceArrayData[0, 0])
     {
     find = true;
     DeleteArraylistCount = Index;
     break;
     }
     }
     }

     if (find)
     {
     Data.RemoveRange(DeleteArraylistCount, 1);
     Data.Insert(DeleteArraylistCount, sourceArrayData);
     }
     else
     {
     Data.Add(sourceArrayData);
     }
     }

     public static void setPLCObject(object PlcObject)
     {
     bool find = false;
     int PLCObjectNum = 0;

     for (int i = 0; i < PLCObject.Count; i++)
     {
     if ((((E_PlcModule.E_PlcModule)PLCObject[i]).IPAddr == ((E_PlcModule.E_PlcModule)PlcObject).IPAddr) && (((E_PlcModule.E_PlcModule)PLCObject[i]).Port == ((E_PlcModule.E_PlcModule)PlcObject).Port))
     {
     PLCObjectNum = i;
     find = true;
     break;
     }
     }

     if (!find)
     {
     PLCObject.Add(PlcObject);
     }
     }

     public static ArrayList GetPLCObject()
     {
     return PLCObject;
     }

     public static bool writePLCData(string Addr, int Size, String[] Data)
     {
     String ReadAddr = "";
     String tempStr = Addr.ToUpper();
     String DeviceName = "";

     if (tempStr.IndexOf("!") == -1)
     {
     DeviceName = tempStr.Substring(0,1);

     if (tempStr.IndexOf(".") == -1)
     {
     if (tempStr.IndexOf("D") != -1)
     {
     ReadAddr = tempStr.Substring(tempStr.IndexOf("D") + 1);
     }

     if (tempStr.IndexOf("R") != -1)
     {
     ReadAddr = tempStr.Substring(tempStr.IndexOf("R") + 1);
     }
     }
     else
     {
     if (tempStr.IndexOf("D") != -1)
     {
     ReadAddr = tempStr.Substring(tempStr.IndexOf("D") + 1, tempStr.IndexOf(".") - 1);
     }

     if (tempStr.IndexOf("R") != -1)
     {
     ReadAddr = tempStr.Substring(tempStr.IndexOf("R") + 1, tempStr.IndexOf(".") - 1);
     }
     }
     }
     else if (tempStr.IndexOf("!") > -1)
     {
     DeviceName = tempStr.Substring(1, 1);

     if (tempStr.IndexOf(".") == -1)
     {
     if (tempStr.IndexOf("D") != -1)
     {
     ReadAddr = tempStr.Substring(tempStr.IndexOf("D") + 1);
     }

     if (tempStr.IndexOf("R") != -1)
     {
     ReadAddr = tempStr.Substring(tempStr.IndexOf("R") + 1);
     }
     }
     else
     {
     if (tempStr.IndexOf("D") != -1)
     {
     ReadAddr = tempStr.Substring(tempStr.IndexOf("D") + 1, tempStr.IndexOf(".") - 2);
     }

     if (tempStr.IndexOf("R") != -1)
     {
     ReadAddr = tempStr.Substring(tempStr.IndexOf("R") + 1, tempStr.IndexOf(".") - 2);
     }
     }
     }

     if (ReadAddr.Trim() == "")
     {
     return false;
     }

     int Index = (Convert.ToInt32(ReadAddr)) / 100000;

     if (Index >= PLCObject.Count)
     {
     return false;
     }

     object PlcObject = null;
     for (int i = 0; i < PLCObject.Count; i++)
     {
     if(PLCObject[Index] is E_PlcModule.E_PlcModule)
     {
     if (((E_PlcModule.E_PlcModule)PLCObject[i]).Name.Substring(11).Trim() == (Index + 1).ToString())
     {
     PlcObject = PLCObject[i];
     }
     }
     }

     if (PlcObject == null)
     {
     return false;
     }

     if (!((E_PlcModule.E_PlcModule)PlcObject).ConnectStatus)
     {
     return false;
     }

     if (Size != Data.Count())
     {
     return false;
     }

     return ((E_PlcModule.E_PlcModule)PlcObject).WritePlcData(DeviceName+ ReadAddr, Size, Data);
     }

     public static bool PLCConnentStatus()
     {

     if (PLCObject.Count == 0)
     {
     return false;
     }

     for (int i = 0; i < PLCObject.Count; i++)
     {
     object PlcObject = PLCObject[i];

     if (!((E_PlcModule.E_PlcModule)PlcObject).ConnectStatus)
     {
     return false;
     }
     }

     return true;
     }

     public static int Get_PLC_Count()
     {
     return PLCObject.Count;
     }
    }
}
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 345 | 人氣 0 | 評價 1650 | 評價/貼文 4.78 | 送出評價 16 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2015/10/27 下午 04:19:20
把資料傳過去、傳過來就好了,沒事幹嘛弄共享來搬石頭砸自己的腳?
作者 : sflam(Raymond)討論區板主 Visual C++ .NET卓越專家VC++一代宗師新手入門優秀好手資訊類作業求救頂尖高手C++一代宗師貼文超過4000則
[ 貼文 4945 | 人氣 9172 | 評價 32290 | 評價/貼文 6.53 | 送出評價 142 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2015/10/27 下午 09:26:22
>但兩隻主程式執行後, 我發現這兩隻的ArrayList資料卻不共享.

當然不共享, 會共享問題才大好嗎!


>這要怎麼做才能達到同一份資料做讀寫動作?

如果是 Win32 的 DLL, 用這裡的方法
  https://msdn.microsoft.com/en-us/library/h90dkhs0(v=vs.90).aspx
或 IPC (Interprocess Communication) 來處理:
  https://msdn.microsoft.com/en-us/library/windows/desktop/aa365574(v=vs.85).aspx

.NET 環境, 看看這個有沒有幫助:
  http://stackoverflow.com/questions/2959998/can-the-same-dll-data-be-shared-by-2-different-processes

  http://stackoverflow.com/questions/56121/ipc-mechanisms-in-c-sharp-usage-and-best-practices
作者 : love007002(爆走笨魚)
[ 貼文 35 | 人氣 1891 | 評價 0 | 評價/貼文 0 | 送出評價 3 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2015/11/1 上午 01:02:18
我後來有找到類似的範例~但我照著打執行後會出現錯誤. 如下原始碼, 請問 AccessViolationException , 嘗試讀取或寫入受保護的記憶體。這通常表示其他記憶體已損毀。 高如何解決呢??

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
     [DllImport("Kernel32.dll")]
     static extern IntPtr CreateFile(String IpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecuritAttributes, uint dwCreationDisposition, uint dwFlagAndAttributes, IntPtr hTemplateFile);

     [DllImport("Kernel32.dll")]
     static extern IntPtr CreateFileMapping(IntPtr hFile, IntPtr lpAttributes, int flProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, String lpName);

     [DllImport("Kernel32.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.ThisCall)]
     static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, int dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, long dwNumberOfBytesToMap);

     [DllImport("Kernel32.dll")]
     static extern bool UnmpViewOfFile(IntPtr lpBaseAddress);

     [DllImport("Kernel32.dll")]
     static extern bool CloseHandle(IntPtr hObject);

     private const uint GENERIC_READ = 0x80000000;

     private const uint GENERIC_WRITE = 0x40000000;

     private const uint FILE_SHARE_READ = 0x00000001;

     private const uint FILE_SHARE_WRITE = 0x00000002;

     private const uint CREATE_ALWYS = 0x02;

     private const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;

     private const int PAGE_READWRITE = 0x04;

     private const int FILE_MAP_WRITE = 0x0002;

     private const int FILE_MAP_READ = 0x0004;

     private static IntPtr INVALID_FILE_VALUE = new IntPtr(-1);

     private const int BUFFER_SIZE = 512, BUFFER_SIZE_HALF = 256;

     private const int ALLOCATE_SIZE = 65536 + 512;

     static void Main(string[] args)
     {
     IntPtr m_FileHandle = CreateFile("FileMap", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, CREATE_ALWYS, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);

     if (m_FileHandle != INVALID_FILE_VALUE)
     {
     IntPtr m_FileObject = CreateFileMapping(m_FileHandle, IntPtr.Zero, PAGE_READWRITE, 0, ALLOCATE_SIZE, null);

     if (m_FileHandle != IntPtr.Zero)
     {
     IntPtr m_BaseAddress = MapViewOfFile(m_FileObject, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, BUFFER_SIZE);

     for (int i = 0; i < BUFFER_SIZE; i++)
     {
     Marshal.WriteByte(m_BaseAddress, i, 0xAA); <== AccessViolationException , 嘗試讀取或寫入受保護的記憶體。這通常表示其他記憶體已損毀。
     }

     byte[] m_ReadDatal = new byte[BUFFER_SIZE];

     for (int i = 0; i < BUFFER_SIZE; i++)
     {
     m_ReadDatal[i] = Marshal.ReadByte(m_BaseAddress, i);
     }

     ShowHex(m_ReadDatal);

     UnmpViewOfFile(m_BaseAddress);
     Console.WriteLine();

     uint m_Granularity = 65536;

     uint m_Offset = 65536 + 30;

     uint m_AddressOffset = m_Offset % m_Granularity;

     uint m_MapOffset = m_Offset - m_AddressOffset;

     m_BaseAddress = MapViewOfFile(m_FileObject, FILE_MAP_WRITE | FILE_MAP_READ, 0, m_MapOffset, BUFFER_SIZE_HALF);

     for (int i = 0; i < BUFFER_SIZE_HALF; i++)
     {
     Marshal.WriteByte(m_BaseAddress, i + (int)m_AddressOffset, 0x77);
     }

     byte[] m_ReadData2 = new byte[BUFFER_SIZE_HALF];

     for (int i = 0; i < BUFFER_SIZE_HALF; i++)
     {
     m_ReadData2[i] = Marshal.ReadByte(m_BaseAddress, i + (int)m_AddressOffset);
     }

     ShowHex(m_ReadData2);

     UnmpViewOfFile(m_BaseAddress);

     CloseHandle(m_FileObject);
     Console.WriteLine();
     }

     CloseHandle(m_FileHandle);
     }

     Console.WriteLine("按下ENTER鍵做下一步資料驗證");
     Console.ReadLine();

     FileStream fs = File.Open("FileMap", FileMode.Open, FileAccess.Read);
     fs.Seek(65566, SeekOrigin.Begin);

     byte [] m_ReadData3 = new byte[BUFFER_SIZE_HALF + 1 ];

     fs.Read(m_ReadData3, 0, m_ReadData3.Length);

     ShowHex(m_ReadData3);
     Console.ReadLine();
     }

     static void ShowHex(byte[] data)
     {
     Console.WriteLine("01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16");
     Console.WriteLine("-------------------------------------------------");
     for (int i = 0; i < data.Length; i += 16)
     {
     Console.Write("{0} | ", i.ToString().PadLeft(4,'0'));
     for (int j = 0; j < 16; j++)
     {
     if (data.Length > i + j)
     {
     Console.Write("{0:X}", data[i + j]);
     }
     }
     Console.WriteLine();
     }
     }
    }
}
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 345 | 人氣 0 | 評價 1650 | 評價/貼文 4.78 | 送出評價 16 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2015/11/1 上午 08:52:47
光 calling convention 就錯了!其他就懶得再看。

給一些參考:
https://en.wikipedia.org/wiki/Protected_mode
https://zh.wikipedia.org/wiki/%E8%A1%8C%E7%A8%8B%E9%96%93%E9%80%9A%E8%A8%8A
https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx
https://msdn.microsoft.com/zh-tw/library/windows/desktop/aa366537%28v=vs.85%29.aspx
https://msdn.microsoft.com/zh-tw/library/windows/desktop/aa366761%28v=vs.85%29.aspx

另外,透過 socket 交換資料也是很多人使用的方法。
作者 : louis_wu(louis)
[ 貼文 59 | 人氣 918 | 評價 220 | 評價/貼文 3.73 | 送出評價 11 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2015/12/11 下午 05:18:34
這個問題跟DLL無關。
你想要共享的資料就存在PLC裡;Process A讀PLC的資料再寫回PLC,Process B就能讀到更新後的資料;反之亦然。
P.S.請勿附上太冗長的程式碼,試著精簡問題。
 板主 : 小朱
 > C# - 討論區
 - 最近熱門問答精華集
 - 全部歷史問答精華集
 - C# - 知識庫
  ■ 全站最新Post列表
  ■ 我的文章收藏
  ■ 我最愛的作者
  ■ 全站文章收藏排行榜
  ■ 全站最愛作者排行榜
  ■  月熱門主題
  ■  季熱門主題
  ■  熱門主題Top 20
  ■  本區Post排行榜
  ■  本區評價排行榜
  ■  全站專家名人榜
  ■  全站Post排行榜
  ■  全站評價排行榜
  ■  全站人氣排行榜
 請輸入關鍵字 
  開始搜尋
 
Top 10
評價排行
C#
1 小朱 6270 
2 蹂躪 2700 
3 HKLN.net 2440 
4 marlon 2130 
5 joe 1320 
6 識丁 910 
7 好說 860 
8 愛睏魚 770 
9 總幹事 720 
10 Demonbane 600 
C#
  專家等級 評價  
  一代宗師 10000  
  曠世奇才 5000  
  頂尖高手 3000  
  卓越專家 1500  
  優秀好手 750  
Microsoft Internet Explorer 6.0. Screen 1024x768 pixel. High Color (16 bit).
2000-2018 程式設計俱樂部 http://www.programmer-club.com.tw/
0.0625