WCF+ duplex + Windows Form Application (ButtonClick) Trouble - c#

I have WCF classes and now project to do. My teacher gave as to write app with streaming and duplex (I know that is impossible, but I found backdoor from this situation - I'm sending pics under 60KB).
My code worked well so far as I start wrote my GUI in Windows Form Application.
When I'm testing it via console - everything work well. But, when I want to use buttons in my GUI i have this exception:
An unhandled exception of type 'System.TimeoutException' occurred in
mscorlib.dll Additional information: This request operation sent to
net.tcp://localhost:7756/Przesylanie did not receive a reply within
the configured timeout (00:00:59.9740007). The time allotted to this
operation may have been a portion of a longer timeout. This may be
because the service is still processing the operation or because the
service was unable to send a reply message. Please consider
increasing the operation timeout (by casting the channel/proxy to
IContextChannel and setting the OperationTimeout property) and ensure
that the service is able to connect to the client.
Here bunch of code:
Service + IService (due to limitation of Stack I put it to one file):
public void WyslijstrumienNaSerwer()
{
IPrzesylanieCallback callback = OperationContext.Current.GetCallbackChannel<IPrzesylanieCallback>();
string sciezka = #"E:\5 semestr\Fras\Se płotek\Lab6\WcfServiceContractZadanie2\Host\bin\Pliki\" + "plik_odebrany.jpg";
string filePath = Path.Combine(System.Environment.SystemDirectory, sciezka);
Console.WriteLine("start");
callback.WyslijStrumien(filePath);
Console.WriteLine(filePath);
Console.WriteLine("meta");
}
namespace WcfServiceContractZadanie2
{
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IPrzesylanieCallback))]
public interface IPrzesylanie
{
[OperationContract]
void WyslijstrumienNaSerwer();
}
[ServiceContract]
public interface IPrzesylanieCallback
{
[OperationContract(IsOneWay = true)]
void WyslijStrumien(string filePath);
}
}
Client + callback + form + References.cs:
namespace Aplikacja
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
PrzesylanieClient klient = new PrzesylanieClient(new InstanceContext(new PrzesylanieCallback()), "NetTcpBinding_IPrzesylanie");
klient.WyslijstrumienNaSerwer();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
public class PrzesylanieCallback : Referencja1.IPrzesylanieCallback
{
public void WyslijStrumien(string filePath)
{
Form1 o1 = new Form1();
// Pobieranie obrazka od klienta
string sciezka = #"E:\5 semestr\Fras\Se płotek\Lab6\WcfServiceContractZadanie2\Aplikacja\bin\Pliki\" + o1.wybrany();
string filePathZrodla = Path.Combine(System.Environment.SystemDirectory, sciezka);
//Otwieranie obrazka
Stream strumien = null;
try
{
FileStream imageFile = File.OpenRead(filePathZrodla);
strumien = (Stream)imageFile;
}
catch(IOException ioe)
{
Console.WriteLine("Wyjatek otwierania pliku: {0}", ioe.ToString());
Console.ReadKey();
throw ioe;
}
// Zapisywanie obrazka
o1.SaveFile(strumien, filePath);
}
}
}
private void btnPrzeslijPlikNaSerwer_Click(object sender, EventArgs e)
{
PrzesylanieClient klient = new PrzesylanieClient(new InstanceContext(new PrzesylanieCallback()), "NetTcpBinding_IPrzesylanie");
klient.WyslijstrumienNaSerwer();
}
public void WyslijstrumienNaSerwer() {
base.Channel.WyslijstrumienNaSerwer();
}
I wrote methods SaveFile which works correctly.
As you see, I'm testing my code in the begining of Main function in Client and that works well.
But when I'm using the same code in Forms it does not work. Compiler is returnig me to References.cs and gives me exception I mentioned earlier.
Waiting for any respone!

My answer does not solve your exception issue; however, it might prevent you from getting a very bad grade. Streaming AND duplex are both supported in WCF.
Streaming:
https://msdn.microsoft.com/en-us/library/ms733742(v=vs.110).aspx
Duplex:
https://msdn.microsoft.com/en-us/library/ms731064(v=vs.110).aspx

Related

How to dispose of Runspace and PowerShell objects from a WPF project using C#

I receive the following error after running my WPF application for the fourth consecutive time:
Fail to create a runspace because you have exceeded the maximum number
of connections allowed : 3 for the policy party : MaxConcurrency.
Please close existing runspace and try again.
This error does not occur when opening the Runspace and PowerShell objects through a using (Runspace rs = RunspaceFactory.CreateInstance())... statement, as the resources seem to be properly disposed.
However, the way that this app is structured I would like to keep the Runspace/PowerShell object open between transactions because it takes a long time to create a remote session with Office 365 and I cannot keep users waiting to re-establish a remote session between every transaction.
When I keep these objects alive I then have to dispose of them manually as they are not contained within a using statement. I am using the following code:
namespace O365Wrapper
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public App()
{
InitializeComponent();
}
[STAThread]
public static void Main()
{
App app = new App();
cOofSettingsView view = new cOofSettingsView();
app.Run(view);
Thread.GetDomain().UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException);
AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit);
}
public static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var ex = (Exception) e.ExceptionObject;
MessageBox.Show(ex.Message);
Environment.Exit(System.Runtime.InteropServices.Marshal.GetHRForException(ex));
}
public static void OnProcessExit(object sender, EventArgs e)
{
cPSConnection.DisposePowerShellEnvironment();
}
}
}
And in cPSConnection:
private static void InitializePowerShellEnvironment()
{
if (_psrunspace == null || _psshell == null)
{
_psrunspace = RunspaceFactory.CreateRunspace();
_psrunspace.Open();
_psshell = PowerShell.Create();
_psshell.Runspace = _psrunspace;
CreatePowerShellSession();
}
}
public static void DisposePowerShellEnvironment()
{
if (_psshell != null)
{
_psshell.Dispose();
}
if (_psrunspace != null)
{
_psrunspace.Dispose();
}
_psshell = null;
_psrunspace = null;
}
According to msdn the Runspace.Dispose method calls Runspace.Close if it has not been closed already.
One last item to note: _psshell and _psrunspace are only instantiated one time there are no incidental duplicate items created that might be lingering - the cPSConnection class is using the Singleton pattern.
The code that I currently have in place is an accumulation of borrowed code from already researching this problem, and I am still having no luck. Not sure where else to look. Any help would be much appreciated. Thanks!

Exception thrown when I pass the appropriate argument to method

I am reviewing source code of a voice chat application.
Here I want to run server program, so that any client can contact to server for voice chat. To run my server program I have to pass server name , port number and network interface that I am going to use for voice chat, after passing required arguments I have to call ServerStart method which is done by clicking on Start Checkbox in design view.If user has not passed appropriate type of arguments then it shows error by calling method ShowError().
Now, When I pass serverName, port number and Network Interface then serverName variable reference to null instead of the passed serverName argument.
Why An exception is thrown when I run server program that exception is "The source was not found, but some or all events logs could not be searched. Inaccessible logs: Security."
public partial class ServerWindow
{
private ChatServer server;
public delegate void SetListBoxItem(string str, string type);
public ServerWindow()
{
InitializeComponent();
ObtainNetworkInterfaces();
}
private void cbStartStop_Checked(object sender, RoutedEventArgs e)
{
if (cbStartStop.IsChecked == true)
{
// validate the port number
try
{
var port = Int32.Parse(tbPortNumber.Text);
server = new ChatServer(port, cbInterfaces.SelectedItem, tbServerName.Text);
server.ClientConnected += ServerOnClientConnected;
server.ClientDisconnected += ServerOnClientDisconnected;
var serverName = tbServerName.Text;
if (string.IsNullOrWhiteSpace(serverName))
{
ShowError();
}
else
{
server.StartServer();
SetControls(false);
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
else
{
if (server == null)
return;
server.StopServer();
SetControls(true);
}
}
private void ShowError()
{
MessageBox.Show(#"Please enter valid port number and/or server name");
cbStartStop.IsChecked = false;
}
The problem seems not to be in the code that you posted. After our chat I would suggest to look at this post try the accepted answer. I have the feeling it will solve your problem.
It is usually helpful to use the exception message in the catch clause. :)

C# TCP/IP not working properly

I am working on a windows service that should collect all incoming TCP/IP streams with this class. It gets started from the services OnStart() void.
However I have encountered that when messages come in from a second sender, the whole communication stops working. The service then does not react to a single connection until you restart it.
public class TCPIP
{
public static Receiver rc = new Receiver();
public class Receiver
{
public delegate void ReceivedEventHandler(string ReceivedText, string Sender);
public event ReceivedEventHandler Received;
public void Start()
{
System.Threading.Thread th = new System.Threading.Thread(internals);
th.Start();
}
private void internals()
{
TcpListener _listener = new TcpListener(1994);
_listener.Start();
while (true)
{
TcpClient rcclient = _listener.AcceptTcpClient();
StreamReader reader = new StreamReader(rcclient.GetStream());
string msg = "";
while (reader.Peek() > -1)
{
msg += Convert.ToChar(reader.Read()).ToString();
}
Received(msg, rcclient.Client.RemoteEndPoint.ToString().Split(Convert.ToChar(":"))[0]);
// Cleanup
rcclient.Close();
reader.Close();
}
}
Could anybody help me out improving this class to answer connections from multiple endpoints, and to not be occupied after one?
Thank you very much in advance.
Just create a thread when you accept some connection, so if it's blocked will not afect the main program.
Btw you can try AcceptTcpClientAsync to prevent blocking calls.

How to close a WCF Client connection

I'm new in WCF, just learning it so far. But I was wondering how to close a WCF client connection from the client side (if it is needed at all? I think so).
I have an interface called
[ServiceContract]
ICalculatorService { blabla... }
The question is on the client side.
So far, I used the following format:
EndpointAddress epAddress = new EndpointAddress("http://localhost:8090/CalculatorService");
ICalculatorService calculatorProxy = ChannelFactory<ICalculatorService>.CreateChannel(new WSHttpBinding(), epAddress);
and now I can:
Result numeralResult = calculatorProxy.AddNumbers(4, 5);
and I got the result and I was happy.
Every single (for example) Button pressing caused the mentioned code to run once.
My question is: is the efficient?
Now I'm thinking of putting this into a separate class, for example:
class CalculatorProxy
{
static EndpointAddress epAddress = new EndpointAddress("http://localhost:8090/CalculatorService");
public static ChannelFactory<ICalculatorService> GetCalculatorProxy()
{
}
public void Dispose() { ... }
}
... and use it like:
using (ICalculatorService calculatorClient = CalculatorProxy.GetCalculatorProxy())
{
calculatorClient.AddNumbers(4, 4);
}
which one would be more efficient?
UPDATE:
Thank you all for your answers.
I finally ended up with this class:
class CalculatorServiceClient : ClientBase<ICalculatorService>, IDisposable
{
static EndpointAddress epAddress = new EndpointAddress("http://localhost:8090/CalculatorService");
ICalculatorService myCalculatorProxy;
public CalculatorServiceClient()
: base(new WSHttpBinding(), epAddress)
{
myCalculatorProxy = ChannelFactory.CreateChannel();
}
public static CalculatorServiceClient GetNewInstance()
{
return new CalculatorServiceClient();
}
public Result AddNumbers(int aIn, int bIn)
{
return myCalculatorProxy.AddNumbers(aIn, bIn);
}
public void Dispose()
{
try
{
Close();
}
catch (CommunicationObjectFaultedException ex)
{
throw new DBCommunicationException("CalculatorServiceClient is in the Faulted state.", ex);
}
catch (Exception ex)
{
throw new DBCommunicationException("Communication is unsuccessful between the CalculatorServiceClient and the CalculatorService.", ex);
}
}
}
And use it in this way:
try
{
using (CalculatorServiceClient calculatorClient = CalculatorServiceClient.GetNewInstance())
{
Result aResult = calculatorClient.AddNUmbers(tbA.Text, tbB.Text);
}
}
catch (DBCommunicationException ex)
{
MessageBox.Show("Service is shut down.");
}
My question is: is this efficient?
You should just close the client when each operation you have done is completed and you don't need anymore to make other calls.
When your work is finished, just close the client using the Close method:
calculatorProxy.Close();
About the Close() method, the MSDN documentation states:
This method causes a CommunicationObject to gracefully transition from
any state, other than the Closed state, into the Closed state. The
Close method allows any unfinished work to be completed before
returning. For example, finish sending any buffered messages.
About your approach, I think the second one is fine and more efficient, because you're also implementing the Dispose pattern and release the used resources (this depends on the resources you're using). Just add the Close() method when the work is finished:
calculatorClient.AddNumbers(4, 4);
calculatorProxy.Close();
Remember also that there's no performance issue creating and closing continuously the WCF clients. This is just a normal habitude.
using (var client = new CalculatorServiceClient())
{
client.SomeMethod();
}
The CalculatorServiceClient object will be available once you add a Service Reference to your Calculator WebService to your client project.
you can call the close method of your proxy class.
like
calculatorProxy.Close();
Alternatively you call the abort method on your service proxy class in case of exception.
try
{
calculatorProxy.SomeMethod();
calculatorProxy.Close();
}
catch
{
calculatorProxy.Abort();
}
Refer to this link for further details
I think you would find it better to put all of that in a class. Establishing an instance of the class can construct the connection and close/dispose when the time comes. Until then, you have an open and active channel to make calls to.

Streaming large files breaks unexpectidely

In my application, I allow user to download large files approx (100MB's) which gets created dynamically and streams directly to the user without storing on the file system. Although it won't breaks all the time, it happens very rarely and very hard to replicate. In order to test it properly, i created a sandbox environment through following class:
public class MvcController : Controller
{
public ActionResult TestWait(int timeToWait = 6000)
{
return new TestWaitResult(timeToWait);
}
}
public class TestWaitResult : ActionResult
{
int _timeToWait;
object o = new object();
TextWriter output;
int _sleepTimer;
public TestWaitResult(int timeToWait)
{
_timeToWait = timeToWait;
_sleepTimer = 10;
}
public override void ExecuteResult(ControllerContext context)
{
context.HttpContext.Response.Buffer = context.HttpContext.Response.BufferOutput = false;
output = context.HttpContext.Response.Output;
while (true)
{
Log("Executing...");
System.Threading.Thread.Sleep(_sleepTimer * 1000);
if ((_timeToWait = _timeToWait - _sleepTimer) <= 0)
{
Log("Timetowait exceeds");
break;
}
}
}
private void Log(string message)
{
lock (o)
{
output.WriteLine("<br/>{0} : {1}", DateTime.Now.ToString("hh:mm:ss.fff"), message);
output.Flush();
}
}
I tried to create the above code simpler to understand the problem.
I deployed the code on the server
http://msongs-test.apphb.com/mvc/testwait?timeToWait=6000
And, after testing it, i found that the response gets break unexpectedly after 10-15 minutes. And, I don't have any clue where it got breaks. I will be extremely happy to know the root cause of the problem.
PS: Although the code runs fine when i deploy it on my local IIS
Edit1: I checked the logs and found that two consecutive errors have been logged
1. HttpException: Server cannot set status after HTTP headers have been sent.
2. HttpException: The remote host closed the connection. The error code is 0x800704CD.

Categories