我不知道是否有人還在尋找一個解決方案,這一點,但它已經好幾次對我來說,因爲我支持的一些遊戲,並且由於寫在Unity的工具,以有限的互操作性與單某些系統(如PIA從Word中閱讀文本,例如),我經常寫OS專用(有時的Windows,MacOS的有時)的可執行文件,並從推出的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();
這裏就是我建立socket服務器:
/// <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);
}
}
。 ..一世' m使用它在Windows上啓動一個命令行工具,該工具使用PIA將文本從Word文檔中提取出來。我嘗試了PIA Unity中的.dll,但遇到了單聲道的互操作問題。我還在MacOS上使用它來調用shell腳本,這些腳本以batchmode方式啓動其他Unity實例,並在那些通過此套接字連接與工具交談的實例中運行編輯器腳本。這很好,因爲我現在可以向用戶發送反饋,調試,監視和響應該過程中的特定步驟等等。
HTH
任何你不使用7zip中的DLL/SDK downloadabe的原因,它允許比任何基於控制檯的技術更好的控制嗎? – Yahia 2012-01-10 18:44:39
這將有助於查看您嘗試使用的流程的代碼,例如您在何處創建流程 – MethodMan 2012-01-10 18:56:40
因爲7z.exe涵蓋了我想要的所有功能。 – Extaze 2012-01-10 20:22:21