Reputation: 73554
Simplified version of what I'm trying to achieve:
I've got all of the above working just fine. I can step through the code and watch the flow of messages as the DisplayAlert() function is called.
What I can't figure out, and I can't believe it's so hard to find how to do something this simple:
- I'd like the DisplayAlert() function in the hosted service interact directly with the WinForm that's hosting it to make the form visible.
All I want to do is set the Visibility to true, and call another function on the WinForm.
This seems to me like it should be as simple as adding a reference to the form, or making a public function on the form and calling it from the service class, but I can't even figure out how to reference Form1 from within the service class.
Am I missing something obvious? How do I even reference the instance of Form1, which is hosting the service?
I've gone down the path of....
Any other suggestions?
I can add code if it helps.
Upvotes: 2
Views: 4877
Reputation: 1953
Using this method you have completely a thread-safe application, and you don't have any limitation.
Service Contract Definition
[ServiceContract]
public interface IService
{
[OperationContract]
void DisplayAlert();
}
Service Implementation
public class Service:IService
{
public void DisplayAlert()
{
var form = Form1.CurrentInstance;
form.MySynchronizationContext.Send(_ => form.Show(), null);
}
}
Program.cs
[STAThread]
static void Main()
{
var host = new ServiceHost(typeof (Service));
host.Open();
Application.SetCompatibleTextRenderingDefault(false);
Application.EnableVisualStyles();
Application.Run(new Form1());
}
Form Implementation
public partial class Form1 : Form
{
public static Form1 CurrentInstance;
public SynchronizationContext MySynchronizationContext;
private bool showForm = false;
public Form1()
{
InitializeComponent();
MySynchronizationContext = SynchronizationContext.Current;
CurrentInstance = this;
}
// use this method for hiding and showing if you want this form invisible on start-up
protected override void SetVisibleCore(bool value)
{
base.SetVisibleCore(showForm ? value : showForm);
}
public void Show()
{
showForm = true;
Visible = true;
}
public void Hide()
{
showForm = true;
Visible = true;
}
}
Client
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Press Enter to show form");
Console.ReadLine();
var client = new ServiceClient();
client.DisplayAlert();
}
}
Upvotes: 11
Reputation: 38079
Can you use a singleton for your service? If so you could implement it like this:
[ServiceContract]
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class MyClass : IMyClass
{
Form1 _f;
public MyClass(Form1 f)
{
_f = f;
}
[OperationContract]
public void Alert(string mess)
{
_f.Text = mess;
}
}
Then when you setup your service host, you instantiate it and pass it the form:
MyClass c = new MyClass(this);
string baseAddress = "http://localhost:12345/Serv";
var host = new ServiceHost(c, new Uri(baseAddress));
Upvotes: 0
Reputation: 3291
In my opinion the answer is "simpol" as a friend says. First of all I would not even bother to follow the path described by you, after all a web service provides all the necessary means to communicate with it. Between your Form1 (which host your service) and your hosted service add a client (where client code is hosted by same Form1) and allow your client to communicate with your service using a duplex channel. In this way your client will know if a message was sent to your service by initiating a a long running request and being notified through the callback. Here is a link with a fancy article related to duplex channels: http://blogs.msdn.com/b/carlosfigueira/archive/2012/01/11/wcf-extensibility-transport-channels-duplex-channels.aspx
P.S: This is a rough suggestion to get you started which for sure can be improved.
Upvotes: 1