मुझे नहीं पता कि कोई अभी भी इसका समाधान ढूंढ रहा है, लेकिन यह मेरे लिए कई बार आया है क्योंकि मैं कुछ खेलों के समर्थन में एकता में एक उपकरण लिख रहा हूं और सीमित अंतःक्रियाशीलता के कारण मोनो के साथ कुछ सिस्टम (जैसे शब्द से पाठ पढ़ने के लिए पीआईए, उदाहरण के लिए), मुझे अक्सर ओएस-विशिष्ट (कभी-कभी विंडोज़, कभी-कभी मैकोज़) निष्पादन योग्य लिखना पड़ता है और उन्हें Process.Start() से लॉन्च करना पड़ता है।
समस्या यह है कि, जब आप इस तरह एक निष्पादन योग्य लॉन्च करते हैं तो यह आपके दूसरे ऐप को अवरुद्ध करने वाले दूसरे थ्रेड में आग लगने जा रहा है, जिससे लटका हुआ है। यदि आप इस समय के दौरान अपने उपयोगकर्ताओं को उपयोगी प्रतिक्रिया प्रदान करना चाहते हैं तो कताई आइकन से परे आपके संबंधित ओएस द्वारा स्वीकार किया गया है, तो आप बहुत खराब हैं। स्ट्रीम का उपयोग करना काम नहीं करेगा क्योंकि थ्रेड अभी भी निष्पादन समाप्त होने तक अवरुद्ध है।
जिस समाधान पर मैंने मारा है, जो कुछ लोगों के लिए चरम लग सकता है लेकिन मुझे लगता है कि मेरे लिए काफी अच्छा काम करता है, दो ऐप्स के बीच विश्वसनीय सिंक्रोनस कॉमर्स सेट अप करने के लिए सॉकेट और मल्टीथ्रेडिंग का उपयोग करना है। बेशक, यह केवल तभी काम करता है जब आप दोनों ऐप्स को संलेखित कर रहे हों। यदि नहीं, तो मुझे लगता है कि आप भाग्य से बाहर हैं। ... मैं देखना चाहता हूं कि यह पारंपरिक धारा दृष्टिकोण का उपयोग करके सिर्फ मल्टीथ्रेडिंग के साथ काम करता है, इसलिए यदि कोई इसे आजमाकर परिणाम पोस्ट करना चाहेगा तो यह बहुत अच्छा होगा।
वैसे भी, यहाँ वर्तमान में मेरे लिए काम कर समाधान है:
मुख्य, या बुला एप्लिकेशन में, मैं कुछ इस तरह करते हैं:
/// <summary>
/// Handles the OK button click.
/// </summary>
private void HandleOKButtonClick() {
string executableFolder = "";
#if UNITY_EDITOR
executableFolder = Path.Combine(Application.dataPath, "../../../../build/Include/Executables");
#else
executableFolder = Path.Combine(Application.dataPath, "Include/Executables");
#endif
EstablishSocketServer();
var proc = new Process {
StartInfo = new ProcessStartInfo {
FileName = Path.Combine(executableFolder, "WordConverter.exe"),
Arguments = locationField.value + " " + _ipAddress.ToString() + " " + SOCKET_PORT.ToString(),
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
proc.Start();
यहाँ मैं कहाँ सॉकेट सर्वर स्थापित है:
/// <summary>
/// Establishes a socket server for communication with each chapter build script so we can get progress updates.
/// </summary>
private void EstablishSocketServer() {
//_dialog.SetMessage("Establishing socket connection for updates. \n");
TearDownSocketServer();
Thread currentThread;
_ipAddress = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0];
_listener = new TcpListener(_ipAddress, SOCKET_PORT);
_listener.Start();
UnityEngine.Debug.Log("Server mounted, listening to port " + SOCKET_PORT);
_builderCommThreads = new List<Thread>();
for (int i = 0; i < 1; i++) {
currentThread = new Thread(new ThreadStart(HandleIncomingSocketMessage));
_builderCommThreads.Add(currentThread);
currentThread.Start();
}
}
/// <summary>
/// Tears down socket server.
/// </summary>
private void TearDownSocketServer() {
_builderCommThreads = null;
_ipAddress = null;
_listener = null;
}
धागे के लिए मेरा सॉकेट हैंडलर है ... ध्यान दें कि आपको कुछ मामलों में एकाधिक धागे बनाना होगा; यही कारण है कि मेरे पास है _builderCommThreads सूची वहाँ में (मैं इसे कोड से पोर्ट कहीं और जहां मैं ऐसी ही कुछ कर रहा था लेकिन एक पंक्ति में कई उदाहरण बुला) है:
/// <summary>
/// Handles the incoming socket message.
/// </summary>
private void HandleIncomingSocketMessage() {
if (_listener == null) return;
while (true) {
Socket soc = _listener.AcceptSocket();
//soc.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 10000);
NetworkStream s = null;
StreamReader sr = null;
StreamWriter sw = null;
bool reading = true;
if (soc == null) break;
UnityEngine.Debug.Log("Connected: " + soc.RemoteEndPoint);
try {
s = new NetworkStream(soc);
sr = new StreamReader(s, Encoding.Unicode);
sw = new StreamWriter(s, Encoding.Unicode);
sw.AutoFlush = true; // enable automatic flushing
while (reading == true) {
string line = sr.ReadLine();
if (line != null) {
//UnityEngine.Debug.Log("SOCKET MESSAGE: " + line);
UnityEngine.Debug.Log(line);
lock (_threadLock) {
// Do stuff with your messages here
}
}
}
//
} catch (Exception e) {
if (s != null) s.Close();
if (soc != null) soc.Close();
UnityEngine.Debug.Log(e.Message);
//return;
} finally {
//
if (s != null) s.Close();
if (soc != null) soc.Close();
UnityEngine.Debug.Log("Disconnected: " + soc.RemoteEndPoint);
}
}
return;
}
बेशक
, आप कुछ सामान अप घोषित करने के लिए की आवश्यकता होगी शीर्ष पर:
private TcpListener _listener = null;
private IPAddress _ipAddress = null;
private List<Thread> _builderCommThreads = null;
private System.Object _threadLock = new System.Object();
... तो लागू निष्पादन, दूसरे छोर की स्थापना में (मैं स्टैटिक्स इस मामले में प्रयोग किया जाता है, तो आप आप क्या कभी आप चाहते उपयोग कर सकते हैं):
private static TcpClient _client = null;
private static Stream _s = null;
private static StreamReader _sr = null;
private static StreamWriter _sw = null;
private static string _ipAddress = "";
private static int _port = 0;
private static System.Object _threadLock = new System.Object();
/// <summary>
/// Main method.
/// </summary>
/// <param name="args"></param>
static void Main(string[] args) {
try {
if (args.Length == 3) {
_ipAddress = args[1];
_port = Convert.ToInt32(args[2]);
EstablishSocketClient();
}
// Do stuff here
if (args.Length == 3) Cleanup();
} catch (Exception exception) {
// Handle stuff here
if (args.Length == 3) Cleanup();
}
}
/// <summary>
/// Establishes the socket client.
/// </summary>
private static void EstablishSocketClient() {
_client = new TcpClient(_ipAddress, _port);
try {
_s = _client.GetStream();
_sr = new StreamReader(_s, Encoding.Unicode);
_sw = new StreamWriter(_s, Encoding.Unicode);
_sw.AutoFlush = true;
} catch (Exception e) {
Cleanup();
}
}
/// <summary>
/// Clean up this instance.
/// </summary>
private static void Cleanup() {
_s.Close();
_client.Close();
_client = null;
_s = null;
_sr = null;
_sw = null;
}
/// <summary>
/// Logs a message for output.
/// </summary>
/// <param name="message"></param>
private static void Log(string message) {
if (_sw != null) {
_sw.WriteLine(message);
} else {
Console.Out.WriteLine(message);
}
}
। ..मैं' मैं विंडोज़ पर एक कमांड लाइन उपकरण लॉन्च करने के लिए इसका उपयोग कर रहा हूं जो वर्ड डॉक से टेक्स्ट खींचने के लिए पीआईए सामान का उपयोग करता है। मैंने पीआईए को यूनिटी में डीडीएस की कोशिश की, लेकिन मोनो के साथ इंटरऑप मुद्दों में भाग गया। मैं इसे मैकोज़ पर भी खोल स्क्रिप्ट्स का आह्वान करने के लिए उपयोग कर रहा हूं जो बैचमोड में अतिरिक्त यूनिटी इंस्टेंस लॉन्च करते हैं और उन सॉकेट कनेक्शन में टूल से बात करते हैं जो उन सॉकेट कनेक्शन में सॉफ़्टवेयर स्क्रिप्ट चलाते हैं। यह बहुत अच्छा है, क्योंकि अब मैं उपयोगकर्ता को फीडबैक भेज सकता हूं, प्रक्रिया में विशिष्ट चरणों को डीबग, मॉनिटर और प्रतिक्रिया दे सकता हूं, और कैटर, और कैटर।
HTH
किसी भी कारण से आप 7zip से DLL/SDK downloadabe का उपयोग नहीं करते हैं जो किसी भी कंसोल-आधारित तकनीक की तुलना में अधिक नियंत्रण के लिए अनुमति देता है? – Yahia
यह उस प्रक्रिया को देखने में मदद करेगा जिसे आपने प्रक्रिया के साथ कोशिश की है उदाहरण के लिए, जहां आप प्रक्रिया – MethodMan
बना रहे हैं क्योंकि 7z.exe सभी कार्यों को शामिल करता है। – Extaze