Still struggling with the server part of my wcf application.
The problem is that the creating a "callback" object within the server class cased a "System.NullReferenceException was unhandled" error.
If I understand right, it happens when I create this server object - ServerClass myServer = new ServerClass();
So I guess I should somehow create a list for server objects and create & add this objects automatically whenever a client makes a connection. Please suggest, what would be the best way of doing that?
Here's my code so far:
namespace server2
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
myServer.eventHappened += new EventHandler(eventFunction);
}
ServerClass myServer = new ServerClass();
// here I instance a new server object.
// yet I believe that I need to make a list, that would store this objects, so that multiple clients would be able to connect,
// and I would be able to pick, to whom I want to send a callback.
void eventFunction(object sender, EventArgs e)
{
label1.Text = myServer.clientName;
}
private ServiceHost duplex;
private void Form2_Load(object sender, EventArgs e) /// once the form loads, create and open a new ServiceEndpoint.
{
duplex = new ServiceHost(typeof(ServerClass));
duplex.AddServiceEndpoint(typeof(IfaceClient2Server), new NetTcpBinding(), "net.tcp://localhost:9080/service");
duplex.Open();
this.Text = "SERVER *on-line*";
}
}
class ServerClass : IfaceClient2Server
{
public event EventHandler eventHappened;
IfaceServer2Client callback = OperationContext.Current.GetCallbackChannel<IfaceServer2Client>();
// ERROR: System.NullReferenceException was unhandled
public string clientName = "noname";
public void StartConnection(string name)
{
clientName = name;
MessageBox.Show(clientName + " has connected!");
eventHappened(this, new EventArgs());
// ERROR: System.NullReferenceException was unhandled :(
callback.Message_Server2Client("Welcome, " + clientName);
}
public void Message_Cleint2Server(string msg)
{
}
public void Message2Client(string msg)
{
}
}
[ServiceContract(Namespace = "server", CallbackContract = typeof(IfaceServer2Client), SessionMode = SessionMode.Required)]
public interface IfaceClient2Server ///// what comes from the client to the server.
{
[OperationContract(IsOneWay = true)]
void St开发者_Python百科artConnection(string clientName);
[OperationContract(IsOneWay = true)]
void Message_Cleint2Server(string msg);
}
public interface IfaceServer2Client ///// what goes from the sertver, to the client.
{
[OperationContract(IsOneWay = true)]
void AcceptConnection();
[OperationContract(IsOneWay = true)]
void RejectConnection();
[OperationContract(IsOneWay = true)]
void Message_Server2Client(string msg);
}
}
Thanks!
This can not be done that way. First of all, the Callback Channel is only available within an operation, not when the instance of the service class is created.
Secondly, the instances of your ServerClass
are created by the WCF service host depending on your WCF configuration. For example, there may be one instance per call (!). So creating an instance yourself and attaching an event handler does not affect the automatically created instances. That's why you get an exception in StartConnection
.
What I'd do in that case is:
- Create a singleton class that publishes the desired event
- Attach a handler to the event from within your main code. This will be the code that listens to events
- Create a public method (like
ConnectionStarted
) which raises the event - Call this method from your
ServerClass
If you don't need to wait for the event handler to finish, you can also raise the event asynchronously in a separate thread. You then have to make sure that the event handler attached in step 2) handles thread contexts properly using for example this.Invoke
(Forms) or this.Dispatcher.BeginInvoke
(WPF).
Try putting that line in the class constructor:
class ServerClass : IfaceClient2Server
{
public event EventHandler eventHappened;
IfaceServer2Client callback;
public ServerClass ()
{
callback = OperationContext.Current.GetCallbackChannel<IfaceServer2Client>();
}
...
}
If still no luck it probably means you can use OperationContext.Current
only inside some operation.
精彩评论