I need to fetch my public IP address from one of the IP address provider URLs. The catch is that these services are not reliable so I must have fallback to different URLs. To obtain maximum performance, I want to initiate WebRequest to all service providers at the same time and consider the result of the one who replies first.
This is the code i wrote. It works absolutely fine. But I have used EventWaitHandle. I just want to know if this is the right way to do it or is it possible to do the same without using WaitHandle (using async/await only)?
private static readonly string[] IpProviders = new string[] {
"http://ipinfo.io/ip", "http://canihazip.com/s",
"http://icanhazip.com", "http://bot.whatismyipaddress.com" };
private static string _publicIp = null;
public static string PublicIp
{
get
{
if (_publicIp == null)
{
_publicIp = FetchPublicIp();
}
return _publicIp;
}
}
private static string FetchPublicIp()
{
using (MyResetEvent manualEvent = new MyResetEvent())
{
foreach (string providerUrl in IpProviders)
{
FetchPublicIp(providerUrl).
ContinueWith(x => OnResult(x.Result, manualEvent));
}
int looped = 0;
do
{
manualEvent.WaitOne();
lock (manualEvent)
{
if (!string.IsNullOrWhiteSpace(manualEvent.Result))
{
return manualEvent.Result;
}
else
{
manualEvent.Reset();
}
looped = manualEvent.Count;
}
} while (looped < IpProviders.Length);
}
return null;
}
private static async Task<string> FetchPublicIp(string providerUrl)
{
string externalip;
try
{
externalip = await new WebClient().DownloadStringTaskAsync(providerUrl);
}
catch (WebException ex)
{
Debug.WriteLine(ex);
externalip = null;
}
if (!string.IsNullOrWhiteSpace(externalip))
{
System.Net.IPAddress ip;
if (System.Net.IPAddress.TryParse(externalip.Trim(), out ip))
{
return ip.ToString();
}
}
return null;
}
private static void OnResult(string s, MyResetEvent manualEvent)
{
try
{
lock (manualEvent)
{
if (manualEvent.Result == null)
{
manualEvent.Result = s;
}
manualEvent.Count++;
manualEvent.Set();
}
}
catch (ObjectDisposedException ex)
{
Debug.WriteLine(ex);
}
}
Here is the MyResetEvent class:
internal class MyResetEvent : EventWaitHandle
{
public MyResetEvent()
: base(false, EventResetMode.ManualReset)
{
}
public string Result { get; set; }
public int Count { get; set; }
}
You are overthinking this way too much. The TPL is there to help you, not fight you!
async Task<string> TakeFirstResponse(string[] urls)
{
return await await Task.WhenAny(
urls.Select(async url =>
await new WebClient().DownloadStringTaskAsync(url)));
}
Why the double await? The Task.WhenAny returns a Task<Task<T>> by design.
#Bas's answer is right on (you should probably accept it actually), but I wanted to offer an even more terse alternative that uses my Flurl library:
async Task<string> TakeFirstResponse(string[] urls)
{
return await await Task.WhenAny(urls.Select(url => url.GetStringAsync()));
}
Flurl.Http is backed by HttpClient, which is newer and generally preferable to WebClient, all other things being equal.
Related
I have a program that calls dozens of methods with varying signatures, but the exception handling inside each one is identical. Is there some way to define a method that can accept a reference to a generic method with various signatures (which rules out a Delegate - right?) and return the object, or void that the method requires? I'm using .NET 4.72.
Here is stripped down version of what I'm currently doing and some pseudo-code of what I'd like to do:
static class StackOverflowQuestion
{
public static void Main(string[] args)
{
// What I'm currently doing:
MethodOne("x");
int ret = MethodTwo(0);
//.
//.
//.
MethodNineteen();
// what I'd like to do is replace MethodOne(), MethodTwo(), ..., Method Nineteen()
// with something like:
RunMethod<void>(MethodOneWork, new object[] {"x"});
ret = RunMethod<int>(MethodTwoWork, new object []{1});
//.
//.
//.
RunMethod<void>(MethodNineteenWork, null);
}
private static void MethodOne(string st)
{
try
{
// the try clause is the only difference between the methods
MethodOneWork(st);
}
catch (MyExceptionA)
{
HandleExceptionA();
return;
}
catch(MyExceptionB)
{
HandleExceptionB();
}
catch(Exception)
{
HandleGenericException();
}
}
private static int MethodTwo(int v)
{
try
{
return MethodTwoWork(v);
}
catch (MyExceptionA)
{
HandleExceptionA();
return -1;
}
catch (MyExceptionB)
{
HandleExceptionB();
return -2;
}
catch(Exception)
{
HandleGenericException();
return 0;
}
}
private static void MethodNineteen()
{
try
{
MethodNineteenWork();
}
catch (MyExceptionA)
{
HandleExceptionA();
return;
}
catch (MyExceptionB)
{
HandleExceptionB();
}
catch(Exception)
{
HandleGenericException();
}
}
/// <summary>
/// Run generic method with generic signature
/// </summary>
private static <T> RunMethod(Delegate MethodxWork, object[] myParams)
{
try
{
new <T>() retVal = MethodxWork(myParams);
return retVal;
}
catch (MyExceptionA)
{
HandleExceptionA();
return new <T>();
}
catch (MyExceptionB)
{
HandleExceptionB();
return new <T>();
}
catch(Exception)
{
HandleGenericException();
return new <T>();
}
}
private static void HandleExceptionB()
{
//handle it
}
private static void HandleExceptionA()
{
//handle it
}
private static void HandleGenericException()
{
//handle it
}
}
internal class MyExceptionB : Exception
{
}
internal class MyExceptionA : Exception
{
}
Sure, just create a few methods whose job it is to handle the exceptions, one for returning results and the other for void, and provide something that does your work.
T Handle<T>(Func<T> call)
{
try
{
return call();
}
catch(YourException ex)
{
return default;
}
}
void Handle(Action call)
{
try
{
call();
}
catch(YourException ex)
{
}
}
After that, you can call your other methods with varying signatures inside there.
var result = Handle(() => SomeCallWithVaryingSignature(...));
Handle(() => SomeOtherCall(...));
I am connecting to an API to get some data that is defined like this:
A client object ClientConnection, which allows one to send requests.
A IApi interface that needs to be passed to the ClientConnection to receive callbacks.
Schematically it looks like this:
// defined in the API dll
public class ClientConnection {
public ClientConnection(IApi api) { ... }
public void request(int reqid, string reqdetails) { ... }
}
interface IApi
{
void receiveData(int reqid, string ans);
}
Now, obviously this is a fairly standard asynchronous way of doing things: send requests through a global object, with a requestid, and receive answers tagged with that requestid.
I want to create a wrapper that is synchronous. What would be the most natural way of doing this? Is there a smart way of using async await, instead of using thread locking and stuff?
class MyWrapper : IApi
{
private ClientConnection _client;
private int _reqToken = 0;
public MyWrapper()
{
_client = new ClientConnection(this);
}
public string getData(string reqdetails)
{
_client.request(_reqToken++, reqdetails);
// what to do here?
}
public void receiveData(int reqid, string data) {
// what to do here?
}
}
Didn't test the code below, but it should give you the idea. Basically you can use ManualResetEvent to be signalled when you receive your result (and don't ever call this without proper timeout):
class MyWrapper : IApi {
private ClientConnection _client;
// here you store your requests
private Dictionary<int, PendingRequest> _pendingRequests = new Dictionary<int, PendingRequest>();
private int _reqToken = 0;
public MyWrapper() {
_client = new ClientConnection(this);
}
public string getData(string reqdetails, TimeSpan timout) {
// if this is multithreaded - lock over _pendingRequests when you add\remove requests there
// and when you increment your _reqToken, or use concurrent collection
using (var token = new PendingRequest()) {
var id = _reqToken;
// lock here
_pendingRequests.Add(id, token);
_client.request(id, reqdetails);
// and here use Interlocked.Increment
_reqToken++;
if (!token.Signal.WaitOne(timout)) {
// and here
_pendingRequests.Remove(id);
// timeout
throw new Exception("timout");
}
// if we are here - we have the result
return token.Result;
}
}
public void receiveData(int reqid, string data) {
// here you might need to lock too
if (_pendingRequests.ContainsKey(reqid)) {
var token = _pendingRequests[reqid];
_pendingRequests.Remove(reqid);
token.Complete(data);
}
}
private class PendingRequest : IDisposable {
public PendingRequest() {
Signal = new ManualResetEvent(false);
}
public ManualResetEvent Signal { get; private set; }
public string Result { get; private set; }
public void Complete(string result) {
this.Result = result;
Signal.Set();
}
public void Dispose() {
Signal.Dispose();
}
}
}
I have been working on a mock-up for an import service which currently runs in sequence. However my mock-up seems to exhibit a strange problem where by sometimes one or two items in the for loop aren't executed.
class Service
{
private Thread _worker;
private bool _stopping;
private CancellationTokenSource _cts;
private ParallelOptions _po;
private Repository _repository;
public void Start(Repository repository)
{
_repository = repository;
_cts = new CancellationTokenSource();
_po = new ParallelOptions {
CancellationToken = _cts.Token
};
_worker = new Thread(ProcessImport);
_worker.Start();
}
public void Stop()
{
_stopping = true;
_cts.Cancel();
if(_worker != null && _worker.IsAlive)
_worker.Join();
}
private void ProcessImport()
{
while (!_stopping)
{
var import = _repository.GetInProgressImport();
if (import == null)
{
Thread.Sleep(1000);
continue;
}
try
{
Parallel.For(0, 1000, _po, i => Work.DoWork(i, import, _cts.Token, _repository));
}
catch (OperationCanceledException)
{
// Unmark batch so it can be started again
batch = _repository.GetBatch(import.BatchId);
batch.Processing = false;
_repository.UpdateBatch(batch);
Console.WriteLine("Aborted import {0}", import.ImportId);
}
catch (Exception ex)
{
Console.WriteLine("Something went wrong: {0}", ex.Message);
}
}
}
}
class Work
{
public static void DoWork(int i, Import import, CancellationToken ct, Repository repository)
{
// Simulate doing some work
Thread.Sleep(100);
HandleAbort(ct);
Thread.Sleep(100);
HandleAbort(ct);
Thread.Sleep(100);
// Update the batch
var batch = repository.GetBatch(import.BatchId);
batch.Processed++;
if (batch.Processed == batch.Total)
{
batch.Finished = DateTime.Now;
batch.Processing = false;
}
repository.UpdateBatch(batch);
}
private static void HandleAbort(CancellationToken ct)
{
if (!ct.IsCancellationRequested)
return;
ct.ThrowIfCancellationRequested();
}
}
With this code, I often find that the batches are never complete and that batch.Processed = 999 or 998.
Can anyone shed any light on what I've done wrong.
Thanks in advance.
Edit:
To be clear about the repository/batch object - I believe in my current mock-up that it is threadsafe
class Repository
{
private ConcurrentBag<Batch> _batchData = new ConcurrentBag<Batch>();
private ConcurrentBag<Import> _importData = new ConcurrentBag<Import>();
public void CreateImport(Import import)
{
_importData.Add(import);
}
public Import GetInProgressImport()
{
var import = _importData
.Join(_batchData, i => i.BatchId, b => b.BatchId, (i, b) => new
{
Import = i,
Batch = b
})
.Where(j => j.Batch.Processed < j.Batch.Total && !j.Batch.Processing)
.OrderByDescending(j => j.Batch.Total - j.Batch.Processed)
.ThenBy(j => j.Batch.BatchId - j.Batch.BatchId)
.Select(j => j.Import)
.FirstOrDefault();
if (import == null)
return null;
// mark the batch as processing
var batch = GetBatch(import.BatchId);
batch.Processing = true;
UpdateBatch(batch);
return import;
}
public List<Import> ListImports()
{
return _importData.ToList();
}
public void CreateBatch(Batch batch)
{
_batchData.Add(batch);
}
public Batch GetBatch(Int64 batchId)
{
return _batchData.FirstOrDefault(b => b.BatchId == batchId);
}
public void UpdateBatch(Batch batch)
{
var batchData = _batchData.First(b => b.BatchId == batch.BatchId);
batchData.Total = batch.Total;
batchData.Processed = batch.Processed;
batchData.Started = batch.Started;
batchData.Finished = batch.Finished;
batchData.Processing = batch.Processing;
}
}
class Import
{
public Int64 ImportId { get; set; }
public Int64 BatchId { get; set; }
}
class Batch
{
public Int64 BatchId { get; set; }
public int Total { get; set; }
public int Processed { get; set; }
public DateTime Created { get; set; }
public DateTime Started { get; set; }
public DateTime Finished { get; set; }
public bool Processing { get; set; }
}
This is only a mock-up so there is no DB or other persistence behind my repository.
Also, I'm not competing my batch on the value of i, but rather the number of iterations of the loop (the work actually having been done) indicated by the Processed property of the batch object.
Thanks
Solution:
I had forgotten about the need synchronise the update of the batch. Should look like:
class Work
{
private static object _sync = new object();
public static void DoWork(int i, Import import, CancellationToken ct, Repository repository)
{
// Do work
Thread.Sleep(100);
HandleAbort(ct);
Thread.Sleep(100);
HandleAbort(ct);
Thread.Sleep(100);
lock (_sync)
{
// Update the batch
var batch = repository.GetBatch(import.BatchId);
batch.Processed++;
if (batch.Processed == batch.Total)
{
batch.Finished = DateTime.Now;
batch.Processing = false;
}
repository.UpdateBatch(batch);
}
}
private static void HandleAbort(CancellationToken ct)
{
if (!ct.IsCancellationRequested)
return;
ct.ThrowIfCancellationRequested();
}
}
Looks like lost updates on batch.Processed. Increments are not atomic. batch.Processed++; is racy. Use Interlocked.Increment.
It seems to me like you don't have a good understanding of threading right now. It's very dangerous to perform such elaborate threading without a good understanding. The mistakes you make are hard to test for but production will find them.
According to MSDN, the overloads of Parallel.For specify the second integer as toExclusive, meaning to goes up to but does not meet that value. In other words, 999 is the expected result, not 1000 - but note also that by starting at "0", your loop does execute 1,000 times.
From a glance, your code is parallel, so make sure you're not seeing the "999" call out of order from the "998" one - this is because by being executed in parallel, your code is inherently unordered, and can easily end up being very randomly rearranged. Also, read up on lock, as your code may be accessing values which it should be waiting for.
How do you execute both of the below methods asynchronously (StoreInSql, StoreInOtherDatabase), and then wait for both results to return before setting the label output message? Can this be done cleanly with the await keyword? Thank you very much.
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.RetryPolicies;
using Microsoft.WindowsAzure.Storage.Table;
using System;
using System.Web.UI;
namespace UpdateStorage
{
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
string email = "test#test.com";
// It takes approximately 300 ms to store in SQL Azure
bool sqlStorageSuccessful = MyAppStorage.StoreInSqlAzureViaEF(email);
// It takes approximately 300 ms to store in Azure Table Storage
bool otherdbStorageSuccessful = MyAppStorage.StoreInAzureTableStorage(email);
if (sqlStorageSuccessful && otherdbStorageSuccessful)
{
labelOutputMessage.Text = "Successfully stored the email.";
}
else
{
labelOutputMessage.Text = "We couldn't store the email, sorry!";
}
// 300ms + 300ms = It takes 600ms for this Page_Load method to complete.
// How can I write it using the "await" keyword so that it only takes ~ 300ms?
}
}
public static class MyAppStorage
{
public static bool StoreInSqlAzureViaEF(string s)
{
try
{
using (MyDataModelContainer db = new MyDataModelContainer())
{
Email e = new Email();
e.EmailAddress = s;
db.SaveChanges();
}
}
catch (Exception)
{
return false;
}
return true;
}
public static bool StoreInAzureTableStorage(string s)
{
try
{
AzureEmailMessage a = new AzureEmailMessage();
a.EmailAddress = s;
a.Save();
}
catch (Exception)
{
return false;
}
return true;
}
}
public static class AzureStorage
{
private static string _ConnectionString = "DefaultEndpointsProtocol=http;AccountName=myaccount;AccountKey=mykey";
static AzureStorage() { }
private static CloudTable GetTableRef(string tableName)
{
CloudStorageAccount account = CloudStorageAccount.Parse(_ConnectionString);
CloudTableClient tableClient = account.CreateCloudTableClient();
IRetryPolicy linearRetryPolicy = new LinearRetry(TimeSpan.FromSeconds(2), 10);
tableClient.RetryPolicy = linearRetryPolicy;
CloudTable table = tableClient.GetTableReference(tableName);
table.CreateIfNotExists();
return table;
}
public static bool SaveObject(ITableEntity entity)
{
try
{
string tableName = entity.GetType().ToString();
int lastNs = tableName.LastIndexOf(".");
if (lastNs > 0)
{
tableName = tableName.Substring(lastNs + 1);
}
CloudTable table = GetTableRef(tableName);
TableOperation insertOperation = TableOperation.Insert(entity);
table.Execute(insertOperation);
return true;
}
catch (Exception)
{
return false;
}
}
}
public class AzureEmailMessage : TableEntity
{
public string EmailAddress { get; set; }
public AzureEmailMessage() { }
public bool Save()
{
return AzureStorage.SaveObject(this);
}
}
}
The best way is to use asynchronous database access (e.g., EF6):
public static class MyAppStorage
{
public static Task<bool> StoreInSqlAsync(string s)
{
return FakeStorageJobAsync(s);
}
public static Task<bool> StoreInOtherDatabaseAsync(string s)
{
return FakeStorageJobAsync(s);
}
private static async Task<bool> FakeStorageJobAsync(string s)
{
// This simulates waiting on a SQL database, or a web service, or any other storage task.
await Task.Delay(300);
return true;
}
}
Then you can consume them naturally using Task.WhenAll and await:
protected async void Page_Load(object sender, EventArgs e)
{
string email = "test#test.com";
bool[] success = await Task.WhenAll(MyAppStorage.StoreInSqlAsync(email),
MyAppStorage.StoreInOtherDatabaseAsync(email));
if (success[0] && success[1])
{
labelOutputMessage.Text = "Successfully stored the email.";
}
else
{
labelOutputMessage.Text = "We couldn't store the email, sorry!";
}
}
In this example, I'm using async void for simplicity, but the ASP.NET team prefers you to use PageAsyncTask as described in the tutorial.
I have an application that opens a socket and sends information over it. This functionality is encapsulated in a class.
I thought that it could be easy to work in parallel if I run this feature with Parallel.ForEach. In this way, each task would open/close a socket and send over it (to the same ip/port). This solution doesn't works.
Second way, I am implementing the socket operation in asynchronous way, and the behavior is that the server receives all data from first task and later the rest of data from other task. From the server side, there's no parallel behavior.
I am searching and reading information about this but I can't solve this problem.
Any ideas? Do you have a complete sample of using socket with Parallel library? Or any complete sample of using sockets in multithreading environment?
Complementary information:
I have a LINQ expression that returns a list of files. This list is processed as this:
Parallel.ForEach(AllFiles, new ParallelOptions { MaxDegreeOfParallelism = _maxDegreeOfParallelism }, currentFile =>
{
ProcessFiles(currentFile);
});
...
ProcessFiles sumarized:
void ProcessFile (string currentFile)
{
MyTcpClient client = null;
try
{
var AllLinesInFiles = // LINQ Expression that returns a list of strings
int port = 23000;
client = new MyTcpServer(ip, port);
foreach (string data in AllLinesInFiles)
{
if (data.Length > 0)
{
if (!client.IsOk)
{
client.Connect(false);
if (!client.IsOk)
break;
}
client.SendMessage(tmpLine2);
}
}
}
catch (Exception ex)
{
...
}
finally
{
if ((client != null) && (client.IsOk))
client.Close();
}
}
MyTcpClient, synchronous version is:
public class MyTcpClient : IDisposable
{
private static object objLock = new object();
public int Port = ...
public IPAddress IPAddress = ...
private string _Host;
private TcpClient _client = null;
private Stream _stream = null;
static MyTcpClient()
{
}
public MyTcpClient(string PassedIPAddress, Int32 PassedPort)
{
try
{
this.IPAddress = PassedIPAddress;
this.Port = PassedPort;
}
catch (Exception ex)
{
...
}
}
public TcpClient TcpClient
{
get { return _client; }
set { _client = value; }
}
public X509Certificate Certificate
{
get { return _certificate; }
set { _certificate = value; }
}
public bool IsOk
{
get
{
return ((_client != null) && (_client.Connected));
}
}
public void Connect(bool isSecure)
{
if (IsOk == false)
{
_client = new TcpClient(this.IPAddress.ToString(), this.Port);
_stream = null;
try
{
NetworkStream networkStream = _client.GetStream();
_stream = (NetworkStream)networkStream;
}
catch (AuthenticationException ex)
{
...
}
catch (Exception ex)
{
...
}
finally
{
}
}
}
public void SendMessage(string message)
{
if (_client != null && IsOk)
{
byte[] dgram = EncodingHelper.GetEncoding().GetBytes(message);
lock (MyTcpClient.objLock)
{
_stream.Write(dgram, 0, dgram.Length);
}
}
}
public void SendMessage(byte[] dgram)
{
if (_client != null && IsOk)
{
lock (MyTcpClient.objLock)
{
_stream.Write(dgram, 0, dgram.Length);
}
}
}
public void Close()
{
this.Dispose();
}
public void Dispose()
{
if (_stream != null)
{
_stream.Close();
}
if (_client != null)
{
_client.Close();
}
}
}
And for the Asynchronous version I have used the example here http://msdn.microsoft.com/en-us/library/bew39x2a.aspx
When I use asynchronous socket client, I update ProcessFile method but, the idea is open/close the socket in this method.