您的位置:首页 > 其它

Revit二次开发之Socket通信实现自动化处理任务(一)

2016-04-14 13:30 393 查看
本例将在Revit ExternalApplication中启动一个服务器,监听客户端发送的消息,并通过这个消息,打开对应的rvt文件,当然你可以基于此定义更多消息并处理这些消息,以实现更多可能。

本例将分为以下几个部分:

1、需要构建一个ExternalApplication常驻Revit,并获取UIApplication对象,用以打开项目文件

2、在ExternalApplication中启动Socket服务器,监听客户端消息

3、由于Revit可能会处理耗时任务,需要建立一个单例的消息队列,管理来自不同客户端的不同消息,以便Revit顺序处理

4、Client程序发送消息给Revit服务器

第一部分,Revit外部应用,以打开一个Revit文档为例

public class Exporter : IExternalApplication
{
private UIApplication uiApp = null;
public Result OnStartup(UIControlledApplication application)
{
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
/创建并启动第二部分创建的服务器
Communicator server = new Communicator("127.0.0.1", 2000);
server.StartListening();
application.ControlledApplication.ApplicationInitialized += OnApplicationInitialized;
return Result.Succeeded;
}

public Result OnShutdown(UIControlledApplication application)
{
return Result.Succeeded;
}

private void OnApplicationInitialized(object sender, ApplicationInitializedEventArgs e)
{
//获取UIApplication对象
Application app = sender as Application;
uiApp = new UIApplication(app);
uiApp.Idling += HandleMessage;
}
//循环处理消息
private void HandleMessage(object sender, IdlingEventArgs e)
{
if (MessageStation.Messages.HasMessage)
{
KeyValuePair<int, string> message = MessageStation.Messages.GetMessage();
try
{
Document document = uiApp.Application.OpenDocumentFile(message.Value);
TaskDialog.Show("document", document.PathName);
}
catch (Exception ex)
{
TaskDialog.Show("error", ex.ToString());
}
}
}
}


第二部分,Socket服务器

internal class Communicator
{
private int target_port = 2000;
private string target_host = "127.0.0.1";
private Socket server_socket = null;
private int connection_max = 10;
internal Communicator()
{
}

internal Communicator(string ip, int port)
{
this.target_host = ip;
this.target_port = port;
}

internal int Port
{
get { return target_port; }
set { target_port = value; }
}

internal string Host
{
get { return target_host; }
set { target_host = value; }
}

internal int MaxConnection
{
get { return connection_max; }
set { connection_max = value; }
}
//建立与客户端的连接
internal bool StartListening()
{
try
{
IPAddress ip_address = IPAddress.Parse(target_host);
IPEndPoint ip_endpoint = new IPEndPoint(ip_address, target_port);
server_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server_socket.Bind(ip_endpoint);
server_socket.Listen(connection_max);
Thread listenThread = new Thread(listen);
listenThread.Start();
return true;
}
catch (Exception ex)
{
return false;
}
}

internal bool StartListening(string ip, int port)
{
this.target_host = ip;
this.target_port = port;
return StartListening();
}

//监听客户端消息
private void listen()
{
while (true)
{
Socket clientSocket = server_socket.Accept();
Thread receiveThread = new Thread(receive);
receiveThread.Start(clientSocket);
}
}
//接收客户端消息
private void receive(object socket)
{
Socket clientSocket = socket as Socket;
if (clientSocket == null)
return;
while (true)
{
try
{
string receiveStr = "";
byte[] receiveBytes = new byte[1024];
int bytes = clientSocket.Receive(receiveBytes, receiveBytes.Length, 0);
receiveStr += Encoding.ASCII.GetString(receiveBytes, 0, bytes);
if (receiveStr != "")
{
//客户端消息入列
MessageStation.Messages.AppendMessage(Thread.CurrentThread.ManagedThreadId, receiveStr);
}
}
catch (Exception ex)
{
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
MessageBox.Show(ex.ToString());
break;
}
}
}
}


第三部分,消息队列,单例

internal class MessageStation
{
//构造函数私有化
private MessageStation()
{
_messages = new Queue<KeyValuePair<int, string>>();
}
//C#语言特性实现单例
internal static readonly MessageStation Messages = new MessageStation();

private Queue<KeyValuePair<int, string>> _messages = null;
//是否有消息
internal bool HasMessage
{
get { return _messages.Count > 0; }
}
//入列
internal void AppendMessage(int clientId, string message)
{
_messages.Enqueue(new KeyValuePair<int, string>(clientId, message));
}
//出列
internal KeyValuePair<int, string> GetMessage()
{
if (_messages.Count > 0)
return _messages.Dequeue();
return new KeyValuePair<int, string>(-1, "no message");
}
}


第四部分,客户端程序,WindowsConsoleApplication

class Client
{
static void Main(string[] args)
{
try
{
int port = 2000;
string host = "127.0.0.1";
IPAddress ip = IPAddress.Parse(host);
IPEndPoint ipe = new IPEndPoint(ip, port);
Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Console.WriteLine("Connecting...");
c.Connect(ipe);
string sendStr = "";
byte[] bs;

//向服务器发送一个文件路径
sendStr = @"C:\Users\Kennan\Desktop\Project1.rvt";
bs = Encoding.ASCII.GetBytes(sendStr);
Console.WriteLine("Send message:" + sendStr);
c.Send(bs, bs.Length, 0);

Thread.Sleep(1000);

//向服务器发送另一个文件路径
sendStr = @"C:\Users\Kennan\Desktop\Project2.rvt";
bs = Encoding.ASCII.GetBytes(sendStr);
Console.WriteLine("Send message:" + sendStr);
c.Send(bs, bs.Length, 0);

Console.ReadLine();
c.Close();
}
catch (ArgumentException e)
{
Console.WriteLine("argumentNullException:{0}", e);
}

catch (SocketException e)
{
Console.WriteLine("SocketException:{0}", e);
}
}
}


所有组件都准备完毕了,接下来可以用Addin文件配置插件了,之后运行Revit,不用打开任何图纸,直接运行Client,Revit会依次打开这两个项目文件,运行的结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: