I have a WCF service running on CentOS 6.6 + Mono 4.2.1. The service works if contract methods are synchronous, but I would like to make use of async if possible (since there is a lot of I/O intensive tasks that go into each request). When I try and implement any of the service as async, though, I get an exception when I run under Mono. I've included a dummy test method for repro:
Server:
[OperationContract]
Task<string> GetUrl(string url);
async public Task<string> GetUrl(string url)
{
MailUtils.LogText(LogLevel.Verbose, () => String.Format("Got request for {0}", url));
string result = String.Empty;
try
{
using (var client = new WebClient())
result = await client.DownloadStringTaskAsync(url);
}
finally
{
MailUtils.LogText(LogLevel.Verbose, () => String.Format("Leaving GetUrl(); Got {0} byte(s)", result.Length));
}
return result;
}
Client (command line utility):
static void Main(string[] args)
{
if (args.Length == 2 && args[0] == "-testasync")
{
try
{
MailSorterServiceClient client = new MailSorterServiceClient();
var task = client.GetUrlAsync(args[1]);
task.Wait();
Console.WriteLine(String.Format("Success: Got {0} byte(s)", (task.Result ?? "").Length));
}
catch(Exception ex)
{
Console.WriteLine(ex.InnerException.Message);
Console.WriteLine(ex.InnerException.StackTrace);
}
return;
}
So far as I can tell the server does not receive the request and the client gets an exception:
Object reference not set to an instance of an object
at System.ServiceModel.Dispatcher.BaseMessagesFormatter.DeserializeReply (System.ServiceModel.Channels.Message message, System.Object[] parameters) [0x000ea] in /root/src/mono-4.2.1/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/BaseMessagesFormatter.cs:289
Additional:
The client generated by Visual Studio has two methods:
Task GetUrlAsync(string url)
and string GetUrl(string url)
If I change my client code to call GetUrl() the request makes it through to the server process and the server log shows:
[12/11/2015 3:06 PM]: Got request for http://www.google.com/
[12/11/2015 3:06 PM]: Leaving GetUrl(); Got 188337 byte(s)
... but the client returns before it receives the response from the server (client gets back an empty string and no indication of an error).
The async code works as expected under Windows.
Is this a bug in Mono or am I doing something wrong?
I am okay with blocking (with a timeout_ on the client but want the server to be async). Any help is appreciated.
Note: A did see a similar sounding problem on Stack Overflow but it sounds like it was addessed in Mono 4.2.
Change your code like this;
Your main method;
if (args.Length == 2 && args[0] == "-testasync")
{
CallWebService(args[1]);
}
Then your web service call;
private static async void CallWebService(string url)
{
try
{
using (MailSorterServiceClient client = new MailSorterServiceClient())
{
var result = await client.GetUrlAsync(url);
Console.WriteLine(result.ToString());
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException.Message);
Console.WriteLine(ex.InnerException.StackTrace);
}
}
Related
I use FluentFTP in my code to transfer data internally to a FTP server. If the connection to the FTP server breaks down during the upload, then there is no exception.
But oddly enough, that doesn't happen with all dates! If I take a *.7z file, there is an exception when the connection is broken.
I'm confused!
When transferring a *.7z file, why does it recognize that the connection was interrupted (service stopped) and restart the connection when the service is available again and with a *.opus file does the program stop in an await?
public class FileWatcher
{
public static async Task Main(string[] args)
{
do
{
Console.WriteLine("Und los geht es!");
await UploadFileAsync();
await Task.Delay(15000);
} while (true);
}
static async Task UploadFileAsync()
{
try
{
string[] filePath = Directory.GetFiles(#"C:\temp\ftpupload", "*",
SearchOption.AllDirectories);
var token = new CancellationToken();
using (AsyncFtpClient client = new AsyncFtpClient())
{
client.Host = "192.168.1.100";
client.Port = 21;
client.Credentials.UserName = "test";
client.Credentials.Password = "test123";
client.Config.EncryptionMode = FtpEncryptionMode.None;
client.Config.InternetProtocolVersions = FtpIpVersion.IPv4;
client.Config.ValidateAnyCertificate = true;
client.Config.ConnectTimeout = 10000;
Console.WriteLine("Connecting......");
await client.AutoConnect(token);
Console.WriteLine("Connected!");
foreach (var erg in filePath)
{
Console.WriteLine("File is uploading: " + erg.GetFtpFileName());
await client.UploadFile(erg, "/" + erg.GetFtpFileName(),
FtpRemoteExists.Overwrite, true, token: token);
Console.WriteLine("File successfully uploaded: " +
erg.GetFtpFileName());
System.IO.File.Delete(erg);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
Error while uploading the file to the server. See InnerException for more info.
I think the problem is that you are not catching the exception from the Main method. The code inside the try-catch block will execute correctly, but if an exception occurs outside the try-catch block, the program will terminate without reporting the error.
So to fix it, you should add a try-catch block in the Main method and inside it, call the UploadFileAsync() method with the await keyword.
Another reason may be the size of the file, or the delay you set in the Main method.
I am a newbie when it comes to MVVM and Web related technologies. We are currently developing an MVVM client app using the latest MVVMLight framework in Visual Studios 2013. The application uses Microsoft's Webapi (latest version) to get data into our model via HTTP requests. Our code executes up to the point where the HTTP request is made, and we have confirmed that the server is getting the request, gathering up the requested data and returning it as JSON. However the client never sees the response, it just continues to wait for the response. Its almost as though we are seeing an issue that seems to do with threads. Where the request was made on one thread, but the response is being received on another. Here is our code (where the HTTP request is made):
public class DataService : IDataService
{
#region Fields
private HttpClient _client;
private LfActivityDataReturnObject _activityReturnObj;
private AdroServices _adroServices;
private bool _selectedProcssingOptionPosted = false;
private bool _activityDataSuccessfullyRetrieved = false;
private decimal _incomingLFEntryId;
#endregion
#region Constructor
public DataService()
{
try
{
//Get command line arguments
string[] arguments = Environment.GetCommandLineArgs();
for (int i = 1; i < arguments.Length; i++)
{
switch (i)
{
case 1:
{
if (!Decimal.TryParse(arguments[i], out _incomingLFEntryId))
{
_incomingLFEntryId = -1;
}
break;
}
}
}
if (_incomingLFEntryId <= 0)
{
throw new ArgumentException(String.Format("Invalid Activity Shortcut Entry ID: {0}", _incomingLFEntryId));
}
}
catch (Exception e)
{
throw e;
}
}
#endregion
#region Methods
public void GetGeneralInformationModel(Action<GeneralInformationModel, Exception> callback)
{
Exception locException = null;
GeneralInformationModel locGeneralInformationModel = null;
if (_adroServices == null)
{
try
{
//Start the HTTP request
GetActivityDataAsync().Wait();
}
catch (Exception e)
{
locException = e;
}
// change? should be for http success but adro failure
if (_activityDataSuccessfullyRetrieved)
{
_adroServices = new AdroServices(_activityReturnObj);
locGeneralInformationModel = new GeneralInformationModel(_adroServices);
}
else
{
Exception e2 = new Exception("Error retrieving activity data in DataService");
locException = e2;
}
}
else
{
locGeneralInformationModel = new GeneralInformationModel(_adroServices);
}
var item = locGeneralInformationModel;
callback(item, locException);
}
//Get data from the repository via the service layer.
private async Task GetActivityDataAsync()
{
try
{
using (this._client = new HttpClient())
{
_client.BaseAddress = new Uri("http://localhost:52512//");
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//Line below is where the app just runs getting no response
HttpResponseMessage caseDataResponse = await _client.GetAsync(string.Format("api/LfUrs/{0}", _incomingLFEntryId));
if (caseDataResponse.IsSuccessStatusCode)
{
_activityReturnObj = await caseDataResponse.Content.ReadAsAsync<LfActivityDataReturnObject>();
if (_activityReturnObj.ReturnCode == 0)
{
_activityDataSuccessfullyRetrieved = true;
}
else
{
_activityDataSuccessfullyRetrieved = false;
}
}
else
{
_activityDataSuccessfullyRetrieved = false;
}
}
}
catch (Exception ex)
{
_activityDataSuccessfullyRetrieved = false;
throw ex;
}
}
We have tried using Fiddler to get more information but Fiddler doesn't seem to be able to reveal any of the details. Also I should mention that we are simulating the server on the local host and as I stated above, we have confirmed the server gets the request and returns the data. My associates and I are starting to think this has something to do with the MVVM Light Framework and the IOC or possibly threading. When we use this same code in a MVVM solution that doesn't use the framework it works. Any help would be sincerely appreciated. Thanks...Mike
I have figured it out. Somehow, in my app.xaml, the Dispatcher.Helper had been moved to the event On_Startup rather than being contained in the class constructor. Additionally I had to move the HTTP stuff into the ADRO services class and make sure it was constructed in the App constructor in app.xaml right after Dispatcher.Helper. But thanks to everyone who participates here on StackOverFlow. This resource is an absolute life-saver. Thanks
I'm new to the Azure Service Bus and am working on a proof of concept using Service Bus Queues, WebJobs, v2.5 of the Azure SDK and Visual Studio 2013
Enqueuing and de-queuing messages from the bus is pretty straightforward, but in order to implement a request-response pattern it looks like I need to use sessions, and that's where the wheels have come off.
Here's the proof-of-concept code from the WebJobs project. It requires that you create two service bus queues: test-request and test-response. The response queue must have Enable Sessions = true
class Program
{
private static string _azureServiceBusConnection;
static void Main()
{
_azureServiceBusConnection = ConfigurationManager.ConnectionStrings["AzureWebJobsServiceBus"].ConnectionString;
var host = new JobHost();
Task.Factory.StartNew(() => Run());
try
{
host.RunAndBlock();
}
catch (Exception ex)
{
Console.WriteLine("RunAndBlock() Unexpected {0}: {1}", ex.GetType().FullName, ex.Message);
throw;
}
}
private static async Task Run()
{
await Task.Delay(1000);
var request = QueueClient.CreateFromConnectionString(_azureServiceBusConnection, "test-request");
var response = QueueClient.CreateFromConnectionString(_azureServiceBusConnection, "test-response");
var sessionid = Guid.NewGuid().ToString();
MessageSession receiver;
try
{
receiver = response.AcceptMessageSession(sessionid);
}
catch (Exception ex )
{
Console.WriteLine("AcceptMessageSession() Unexpected {0}: {1}", ex.GetType().FullName, ex.Message);
throw;
}
var payload = new RequestModel {ID = Guid.NewGuid(), Delay = 1};
var message = new BrokeredMessage(payload) {ReplyToSessionId = sessionid};
try
{
request.Send(message);
}
catch (Exception ex)
{
Console.WriteLine("Send() Unexpected {0}: {1}", ex.GetType().FullName, ex.Message);
throw;
}
var receivedMessage = receiver.Receive(TimeSpan.FromSeconds(5));
if (receivedMessage != null)
{
// Request processed within the timeout period
var responseBody = receivedMessage.GetBody<RequestModel>();
Console.WriteLine("Inline response to {0}", responseBody.ID );
receivedMessage.Complete();
}
else
{
// Request processing timed out - should be handled by LocalResponseQueue WebJob (see below)
Console.WriteLine("ERROR: Response timed out.");
}
}
}
public class RequestModel
{
public Guid ID { get; set; }
public int Delay { get; set; }
}
public class RemoteSystemRequestQueue
{
// Simulates the processing of the request on a remote system
public static void ProcessQueueMessage([ServiceBusTrigger("test-request")] BrokeredMessage request, [ServiceBus("test-response")] out BrokeredMessage response)
{
// Wait for the prescribed delay, then bounce the request payload back via the response queue
var requestBody = request.GetBody<RequestModel>();
Console.WriteLine("Recieved Request {0}, delay={1}", requestBody.ID, requestBody.Delay);
Task.Delay(requestBody.Delay * 1000).Wait();
response = new BrokeredMessage(requestBody) {SessionId = request.ReplyToSessionId};
request.Complete();
Console.WriteLine("Completed Request {0}, delay={1}", requestBody.ID, requestBody.Delay);
}
}
public class LocalResponseQueue
{
// Should be called ONLY when the processing took longer than the timeout
public static void ProcessQueueMessage([ServiceBusTrigger("test-response")] BrokeredMessage message, TextWriter logger)
{
var msgBody = message.GetBody<RequestModel>();
Console.WriteLine("ResponseFactory Recieved Reply {0}", msgBody.ID);
}
}
When Enable Sessions = true on the test-response queue, the call to host.RunAndBlock() throws a System.InvalidOperationException with the message
It is not possible for an entity that requires sessions to create a non-sessionful message receiver
The output looks like this:
Found the following functions:
ServiceBusPoc.RemoteSystemRequestQueue.ProcessQueueMessage
ServiceBusPoc.LocalResponseQueue.ProcessQueueMessage
Executing: 'RemoteSystemRequestQueue.ProcessQueueMessage' because New service bus message detected on 'test-request'.
Recieved Request 4f000f8f-dd69-4909-9ec4-020fec12366c, delay=1
RunAndBlock() Unexpected System.InvalidOperationException: It is not possible for an entity that requires sessions to create a non-sessionful message receiver.
TrackingId:7836ac90-6920-4e6c-b7f1-cf648e2a17e5_G38_B10,TimeStamp:10/6/2015 12:37:05 PM
Note that the exception was thrown BEFORE the RemoteSystemRequestQueue object could complete processing the queued request
I presume from this that this means that WebJobs can't handle sessions (at least in the manner in which I'm using them)
Can anyone shed any light on this, or am I going to have to give up on WebJobs?
What version of the WebJobs SDK are you using? In our current v1.1.0 release (still prerelease) we've started opening up more options for ServiceBus configuration. See:
ServiceBusConfiguration
Custom MessagingProvider
You can basically now control more of the messaging details that were previously buried in the SDK internals. However, regarding full Session support, we do have this open issue that might be closer to your scenario. If so, and if you can't get things to work with the above, please add your scenario details to that issue. Thanks.
I am writing a simple C# console application, whose main job is, when given a set of URLs, to ping those URLs and report whether or not an HTTP 200 OK result was returned. The real life data set is in the area of 20,000 URLs to test (to verify that an en-masse edit did not ruin any of the pages).
Currently, the code that checks the response looks like this:
public UrlTestResult TestUrl(string url)
{
if (string.IsNullOrWhiteSpace(url))
{
throw new ArgumentNullException("url");
}
using (var client = new HttpClient())
{
try
{
Task<HttpResponseMessage> message = client.GetAsync(url);
if (message == null || message.Result == null)
{
return new FailedUrlTestResult(url, "No response was returned.");
}
if (message.Result.StatusCode == HttpStatusCode.OK)
{
return new SuccessfulUrlTestResult(url);
}
return new FailedUrlTestResult(url, "{0}: {1}".Format((int)message.Result.StatusCode, message.Result.ReasonPhrase));
}
catch (Exception ex)
{
return new FailedUrlTestResult(url, "An exception occurred: " + ex);
}
}
}
This code does work for smaller sets of data. Even if I iterate over the collection of URLs using Parallel.ForEach instead of a normal foreach, it behaves fine. After running for a few minutes or so, however, when parsing the 20,000 dataset, IIS Express (hosting localhost) will crash.
I'm guessing that my options are:
Run out of IIS and see if that works
Throttle the number of requests to give IIS Express a chance to breathe (trick here is how much to throttle)
Test the URLs in smaller chunks (similar to the second option)
What I am wondering is:
Is there a "cheaper" way to ping a URL and get its HTTP response back than HttpClient?
Are there any configuration options for IIS or IIS Express that I should be taking into consideration?
EDIT: I'm finding that IIS Express seems to simply be running out of memory. Pictured is the instance where the crash occurs:
Which means that IIS Express is holding on to memory that it obviously doesn't need to be (because once the request is over, I don't care about it anymore). Don't know if this'll help solve my problem any, though.
I simply changed to running localhost out of IIS instead of IIS Express. The memory usage was about the same, but it never crashed at any point for the ten minutes that the application was running. I also took Gabi's comment/suggestion and made HttpClient only be instantiated one time instead of once per test. The final code looks like this:
public sealed class UrlTester : IUrlTester
{
private readonly HttpClient httpClient = new HttpClient();
public UrlTestResult TestUrl(string url)
{
if (string.IsNullOrWhiteSpace(url))
{
throw new ArgumentNullException("url");
}
try
{
Task<HttpResponseMessage> message = httpClient.GetAsync(url);
if (message == null || message.Result == null)
{
return new FailedUrlTestResult(url, "No response was returned.");
}
if (message.Result.StatusCode == HttpStatusCode.OK)
{
return new SuccessfulUrlTestResult(url);
}
return new FailedUrlTestResult(url, "{0}: {1}".FormatCurrentCulture((int)message.Result.StatusCode, message.Result.ReasonPhrase));
}
catch (Exception ex)
{
return new FailedUrlTestResult(url, "An exception occurred: " + ex);
}
}
public void Dispose()
{
if (httpClient != null)
{
httpClient.Dispose();
}
}
}
And the caller to this class utilizes C#'s using statement to ensure that the HttpClient instance is properly disposed of.
Is there any possible that I can ensure that the application does not fall if app can not connect to the server using await socket.ConnectAsync(server) I get this exc:
But the biggest problem is I get this exception only occasionally and randomly. Try and catch completely unresponsive and applications fall. So I need something if I cannot connect firts time dont go to exception but try it again.
My code:
public async Task _connect(string token, string idInstalation, string lang)
{
try
{
if (token != null)
{
socket.SetRequestHeader("Token", token);
socket.SetRequestHeader("Lang", lang);
socket.SetRequestHeader("idInstallation", idInstalation);
}
await socket.ConnectAsync(server);
System.Diagnostics.Debug.WriteLine("Connected");
writer = new DataWriter(socket.OutputStream);
messageNumber = 1;
}
catch (Exception)
{
var dialog = new MessageDialog("Cannot connect to UNIAPPS server", "Error").ShowAsync();
}
}