Tôi không biết liệu có ai vẫn đang tìm giải pháp cho việc này hay không, nhưng nó đã xuất hiện nhiều lần vì tôi đang viết một công cụ trong Unity để hỗ trợ một số trò chơi và do khả năng tương tác giới hạn của một số hệ thống với mono (ví dụ như PIA để đọc văn bản từ Word), tôi thường phải viết các tệp thực thi OS (cụ thể là Windows, đôi khi MacOS) và khởi chạy chúng từ Process.Start().
Sự cố là khi bạn khởi chạy tệp thực thi như thế này, nó sẽ kích hoạt trong một chuỗi khác chặn ứng dụng chính của bạn, gây treo. Nếu bạn muốn cung cấp phản hồi hữu ích cho người dùng của mình trong thời gian này ngoài các biểu tượng quay được gợi lên bởi hệ điều hành tương ứng của bạn, thì bạn đã hơi say. Sử dụng luồng sẽ không hoạt động vì luồng vẫn bị chặn cho đến khi quá trình thực hiện kết thúc. Các giải pháp tôi đã nhấn vào, mà có thể có vẻ cực đoan đối với một số người nhưng tôi tìm thấy các công trình khá tốt đối với tôi, là sử dụng ổ cắm và đa luồng để thiết lập comms đồng bộ đáng tin cậy giữa hai ứng dụng. Điều này có nghĩa là: Tất nhiên, điều này chỉ hoạt động nếu bạn là tác giả của cả hai ứng dụng. Nếu không, tôi nghĩ bạn không may mắn. ... Tôi muốn xem liệu nó có hoạt động với đa luồng bằng cách sử dụng phương pháp truyền thống hay không, vì vậy nếu ai đó muốn thử điều đó và đăng kết quả ở đây sẽ thật tuyệt vời.
Dù sao, đây là giải pháp hiện đang làm việc cho tôi:
Trong ứng dụng chính, hoặc gọi điện thoại, tôi làm điều gì đó như thế này:
/// <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();
Đây là nơi tôi thiết lập máy chủ 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;
}
Đây là trình xử lý socket của tôi cho chuỗi ... lưu ý rằng bạn sẽ phải tạo nhiều luồng trong một số trường hợp; đó là lý do tại sao tôi có mà _builderCommThreads Danh sách trong đó (tôi chuyển nó từ mã ở nơi khác, nơi tôi đang làm một cái gì đó tương tự nhưng gọi nhiều trường hợp liên tiếp):
/// <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;
}
Tất nhiên, bạn sẽ cần phải khai báo một số nội dung lên ở đầu trang:
private TcpListener _listener = null;
private IPAddress _ipAddress = null;
private List<Thread> _builderCommThreads = null;
private System.Object _threadLock = new System.Object();
... sau đó trong thực thi gọi, thiết lập đầu kia (tôi đã sử dụng tĩnh trong trường hợp này, bạn có thể sử dụng những gì mà bạn muốn):
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);
}
}
. ..TÔI' m bằng cách sử dụng công cụ này để khởi chạy công cụ dòng lệnh trên Windows sử dụng công cụ PIA để kéo văn bản ra khỏi tài liệu Word. Tôi đã thử PIA các .dll trong Unity, nhưng chạy vào các vấn đề interop với mono. Tôi cũng đang sử dụng nó trên MacOS để gọi các kịch bản lệnh shell khởi chạy các cá thể Unity bổ sung trong batchmode và chạy các kịch bản trình soạn thảo trong các trường hợp đó nói lại công cụ trên kết nối socket này. Thật tuyệt vời, bởi vì bây giờ tôi có thể gửi phản hồi cho người dùng, gỡ lỗi, theo dõi và phản hồi các bước cụ thể trong quy trình, v.v. v.v.
HTH
lý do nào bạn không sử dụng DLL/SDK downloadabe từ 7zip cho phép kiểm soát tốt hơn nhiều so với bất kỳ kỹ thuật dựa trên bàn điều khiển nào? – Yahia
Nó sẽ giúp xem mã mà bạn đã thử với Quy trình ví dụ bạn đang tạo Quy trình – MethodMan
Vì 7z.exe bao gồm tất cả các chức năng tôi muốn. – Extaze