我不知道是否有人还在寻找一个解决方案,这一点,但它已经好几次对我来说,因为我支持的一些游戏,并且由于写在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