I am using upload function in my desktop application. i want if upload function become unsuccessful then this method retry to upload it. Currently when upload is unsuccessful then it be me error of unhandled exception .i need solution of this
**This is function**
async Task Uploaded()
{
using (var dbx = new DropboxClient(token))
{
bmp = new Bitmap(picboxcapture.Image);
string folder = "/folder/"+Login.recuser+"";
string filename = DateTime.Now.ToString() + " " + " " + MyTodo_Project.rectsk + ".JPG";
string URL = picboxcapture.Image.ToString();
ImageConverter converter = new ImageConverter();
MemoryStream(File.ReadAllBytes(#"C:\Users\home\Downloads\FazalNEwTEst.JPG"));
byte[] bytes = (byte[])converter.ConvertTo(picboxcapture.Image, typeof(byte[]));
var mem = new MemoryStream(bytes);
var updated = dbx.Files.UploadAsync(folder + "/" + filename,
WriteMode.Overwrite.Instance, body: mem);
updated.Wait();
var tx = dbx.Sharing.CreateSharedLinkWithSettingsAsync(folder + "/" + filename);
tx.Wait();
URL = tx.Result.Url;
}
}
**The function call**
private async void save_Load(object sender, EventArgs e)
{
await Uploaded();
}
I want that when upload unsuccessful then it will retry to upload it in page load event . how can
i do this in C#
Just write your own retry handler. Or use Polly (recommended, as it's a mature and very successful library).
However, this is an example of how you might build your own.
Given
public class RetriesExceededException : Exception
{
public RetriesExceededException() { }
public RetriesExceededException(string message) : base(message) { }
public RetriesExceededException(string message, Exception innerException) : base(message, innerException) { }
}
public static async Task RetryOnExceptionAsync(int retryCount, int msDelay, Func<Task> func)
{
for (var i = 0; i < retryCount; i++)
{
try
{
await func.Invoke();
return;
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
if (i == retryCount - 1)
throw new RetriesExceededException($"{retryCount} retries failed", ex);
}
await Task.Delay(msDelay)
.ConfigureAwait(false);
}
}
Usage
await RetryOnExceptionAsync(3, 1000, Uploaded);
Related
I am trying to download an XML file of size 85MB in my Xamarin iOS iPad App.
Sometimes download completes successfully, but other times download hangs inbetween somewhere without giving any error. Progress stops.
AWS SDK version:
AWSSDK.S3 3.3.20.4
AWSSDK.Core 3.3.24.8
I tried both methods 1- TransferUtility 2- GetObject.
Here is my code:
var clientRequest = new AmazonS3Client(AWSAccessKey,
AWSSecretKey,
Amazon.RegionEndpoint.USEast1);
try
{
GetObjectRequest request = new GetObjectRequest
{
BucketName = AWSBucketName,
Key = Path + "File1.xml"
};
using (GetObjectResponse response = await clientRequest.GetObjectAsync(request))
{
response.WriteObjectProgressEvent += displayDownloadProgress;
await response.WriteResponseStreamToFileAsync(destPath, false);
}
}
catch (AmazonS3Exception e)
{
Console.WriteLine("Error encountered ***. Message:'{0}' when writing an object", e.Message);
}
catch (Exception e)
{
Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
}
I tried both methods one by one.
var utility = new TransferUtility(cas.AWSAccessKey,
cas.AWSSecretKey,
Amazon.RegionEndpoint.USEast1);
TransferUtilityDownloadRequest dr = new TransferUtilityDownloadRequest();
dr.BucketName = AWSBucketName;
dr.Key = Path + "File1.xml";
dr.FilePath = destPath;
dr.WriteObjectProgressEvent += displayDownloadProgress;
await utility.DownloadAsync(dr);
public void displayDownloadProgress(object sender, WriteObjectProgressArgs args)
{
Debug.WriteLine("Download Progress: " + (args.PercentDone));
InvokeOnMainThread(() =>
{
BTProgressHUD.ShowContinuousProgress("Download Progress: " + args.PercentDone.ToString() + "%", ProgressHUD.MaskType.Gradient);
});
if (args.PercentDone >= 100)
{
BTProgressHUD.Dismiss();
}
}
I have a question in regards to the BitmapFactory. I am using Xamarin and I'm trying to Decode a stream retrieved from Internal Storage, but whenever I try to Decode with the Bitmap Factory, it does not return a Bitmap. But if I retrieve the EXACT same image from a URL and Decode with Bitmap Factory, it works just fine. This doesn't make any sense, please help!
public static async Task<Bitmap> HandleContentImage(Post post)
{
var charsToRemove = new string[] { "/", ".com", ":", "-", ".", "_", ";" };
var ContentImageUri = post.image_url;
foreach (var c in charsToRemove)
{
ContentImageUri = ContentImageUri.Replace(c, string.Empty);
}
HomeService homeService = new HomeService();
try
{
Stream CachedContentImageStream = await homeService.LoadImageFromCache(ContentImageUri + ".jpg");
if (CachedContentImageStream != null)
{
Bitmap ContentImageBitmap = await BitmapFactory.DecodeStreamAsync(CachedContentImageStream);
return ContentImageBitmap;
}
else
{
byte[] ContentImageArray = await homeService.DownloadImageBytesAsync(post.image_url);
Stream ContentImageStream = new MemoryStream(ContentImageArray);
await homeService.SaveImageToCache(ContentImageStream, ContentImageUri + ".jpg");
Bitmap ContentImageBitmap = await BitmapFactory.DecodeStreamAsync(ContentImageStream);
return ContentImageBitmap;
}
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.Message);
return null;
}
}
I have a service that runs a c# method to sync a database with active directory at a specified interval. This code has worked in a test environment and now putting it on a different server it is returning the following message:
The server encountered an error processing the request. Please see the
service help page for constructing valid requests to the service.
The help page looks like this:
But the "SyncActiveDirectory" URI is giving me this error:
This is a new server. Maybe i am missing something that needs to be installed or a setting in IIS? Any help would be much appreciated.
EDIT:
Here is the method that called the webget:
private void SyncActiveDirectoryServiceCall()
{
WriteIntoLogFile("Start _schedulerService.SyncActiveDirectoryServiceCall()");
try
{
var reader = new AppSettingsReader();
var serviceurl = reader.GetValue("ServiceUrl", typeof(string));
var client = new RestSharp.RestClient(serviceurl.ToString());
var request = new RestSharp.RestRequest("SyncActiveDirectory", RestSharp.Method.GET);
var response = client.Execute(request);
WriteIntoLogFile(response.Content);
}
catch (WebException ex)
{
using (WebResponse response = ex.Response)
{
HttpWebResponse httpResponse = (HttpWebResponse)response;
WriteIntoLogFile("Error code: " + httpResponse.StatusCode);
using (Stream data = response.GetResponseStream())
using (var reader = new StreamReader(data))
{
string text = reader.ReadToEnd();
WriteIntoLogFile("STREAMED: " + text);
}
}
WriteIntoLogFile("TRY-CATCH: " + ex.ToString());
}
WriteIntoLogFile("End _schedulerService.SyncActiveDirectoryServiceCall()");
}
And here is the method being called:
namespace SyncActiveDirectory
{
public class SyncLocalWithLDAP : ISyncLocalWithLDAP
{
private List<GenericUser> users { get; set; }
private List<GenericUser> roles { get; set; }
[WebGet(UriTemplate = "SyncActiveDirectory")]
public void SyncActiveDirectory()
{
string constr = GetConnectionStringValue("ProteusMMXCustomerDB");
string usr = GetAppsettingValue("ldap_login_username");
string pss = GetAppsettingValue("ldap_login_password");
string filePath = string.Empty;
ActiveDirectoryWrapper wrapper = new ActiveDirectoryWrapper();
if (!Directory.Exists(WebConfigurationManager.AppSettings["LogFolderPath"] + "ServiceLog"))
{
Directory.CreateDirectory(WebConfigurationManager.AppSettings["LogFolderPath"] + "ServiceLog");
}
if (!File.Exists(WebConfigurationManager.AppSettings["LogFolderPath"] + "ServiceLog" + "/" + "SyncLog.txt"))
{
File.Create(WebConfigurationManager.AppSettings["LogFolderPath"] + "ServiceLog" + "/" + "SyncLog.txt").Dispose();
}
filePath = WebConfigurationManager.AppSettings["LogFolderPath"] + "ServiceLog" + #"\" + "SyncLog.txt";
using (StreamWriter w = File.AppendText(filePath))
{
Log("Constr - " + constr + " , u - " + usr + " p - " + pss, w);
try
{
Log("Start sync outer", w);
SyncLocalWithLDAP_Users_Roles(constr, usr, pss, w);
Log("End sync outer", w);
}
catch (Exception ex)
{
Log("Error: " + ex.Message, w);
}
}
}
EDIT:
Pic of htm file added to that directory.
EDIT:
If this helps here is Chrome Developer Tools headers:
I have some nested async methods calling each other and it is confusing. I am trying to convert a project which downloads the files in an async download.
On the click of the download button this is the method triggered:
private async void enableOfflineModeToolStripMenuItem_Click(object sender, EventArgs e)
{
for(int i = 0; i < _playlists.Count; i++)
{
DoubleDimList.Add(new List<String>());
for(int j = 0; j < 5; j++)
{
string sMp3 = IniReadValue(_playlists[i], "Track " + j);
DoubleDimList[i].Add(sMp3);
}
await Task.Run(() => _InetGetHTMLSearchAsyncs(DoubleDimList[i]));
}
}
It creates a 2d List which at the end looks like this DoubleDimList[3][20].
At the end of each sublist I am doing an async download as you can see. The method looks like this
private async Task _InetGetHTMLSearchAsyncs(List<string> urlList)
{
foreach (var url in urlList)
{
await Task.Run(() => _InetGetHTMLSearchAsync(url));
}
}
the _InetGetHTMLSearchAsync method looks like this and here is where it gets tricky
private async Task _InetGetHTMLSearchAsync(string sTitle)
{
Runs++;
if (AudioDumpQuery == string.Empty)
{
//return string.Empty;
}
string sResearchURL = "http://www.audiodump.biz/music.html?" + AudioDumpQuery + sTitle.Replace(" ", "+");
try
{
using (var client = new WebClient())
{
client.Headers.Add("Referer", #"http://www.audiodump.com/");
client.Headers.Add("user-agent", "Mozilla / 5.0(Macintosh; Intel Mac OS X 10_9_3) AppleWebKit / 537.75.14(KHTML, like Gecko) Version / 7.0.3 Safari / 7046A194A");
client.DownloadStringCompleted += Client_DownloadStringCompleted;
await Task.Run(() => client.DownloadStringAsync(new Uri(sResearchURL)));
}
}
catch (Exception ex)
{
Console.WriteLine("Debug message: " + ex.Message + "InnerEx: " + ex.StackTrace);
Console.WriteLine("Runs: " + Runs);
return;
}
}
On Client_DownloadStringCompleted there is another async method called. Here it is
private async void Client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
string[] sStringArray;
string aRet = e.Result;
string[] aTable = _StringBetween(aRet, "<BR><table", "table><BR>", RegexOptions.Singleline);
if (aTable != null)
{
string[] aInfos = _StringBetween(aTable[0], ". <a href=\"", "<a href=\"");
if (aInfos != null)
{
for (int i = 0; i < 1; i++)
{
sStringArray = aInfos[i].Split('*');
sStringArray[0] = sStringArray[0].Replace("'", "'");
aLinks.Add(sStringArray[0]);
}
await Task.Run(() => DownloadFile(aLinks[FilesDownloaded]));
}
}
}
From there, surprise! Another async call.
private async Task DownloadFile(string url)
{
try
{
using (var client = new WebClient())
{
client.Headers.Add("Referer", #"http://www.audiodump.biz/");
client.Headers.Add("user-agent", "Mozilla / 5.0(Macintosh; Intel Mac OS X 10_9_3) AppleWebKit / 537.75.14(KHTML, like Gecko) Version / 7.0.3 Safari / 7046A194A");
client.DownloadFileCompleted += Client_DownloadFileCompleted;
await Task.Run(() => client.DownloadFileTaskAsync(url, mp3Path + "\\" + count + ".mp3"));
}
}
catch (Exception Ex)
{
Console.WriteLine("File download error: " + Ex.StackTrace);
}
}
Now the first part after the creation of the 2d List is to retrieve the download links of the mp3s. The second part is to download the mp3 as soon as a valid URL was provided. It works but in a bizarre way. Instead of downloading the file normally(1st, 2nd, 3rd...), it will download randomly the files(1st, 5th, 8th...).
It is my first go for async download and boy, I am already far from my limits.
Where am I messing this up? And the main question, will this ever work the way it is supposed to work?
Your code looks pretty good, except for two things:
You shouldn't be using Task.Run. The primary use case for Task.Run is for moving CPU-bound work off a GUI thread so it doesn't block the UI. I have a series on the proper use of Task.Run that goes into this in detail.
You should use a consistent asynchronous pattern, ideally TAP. Your code is currently using TAP everywhere except in _InetGetHTMLSearchAsync, which is using EAP. This is what is causing the odd behavior you're seeing.
A fixed _InetGetHTMLSearchAsync would look something like this:
private async Task _InetGetHTMLSearchAsync(string sTitle)
{
Runs++;
string sResearchURL = "http://www.audiodump.biz/music.html?" + AudioDumpQuery + sTitle.Replace(" ", "+");
try
{
using (var client = new WebClient())
{
client.Headers.Add("Referer", #"http://www.audiodump.com/");
client.Headers.Add("user-agent", "Mozilla / 5.0(Macintosh; Intel Mac OS X 10_9_3) AppleWebKit / 537.75.14(KHTML, like Gecko) Version / 7.0.3 Safari / 7046A194A");
string[] sStringArray;
string aRet = await client.DownloadStringTaskAsync(new Uri(sResearchURL));
string[] aTable = _StringBetween(aRet, "<BR><table", "table><BR>", RegexOptions.Singleline);
if (aTable != null)
{
string[] aInfos = _StringBetween(aTable[0], ". <a href=\"", "<a href=\"");
if (aInfos != null)
{
for (int i = 0; i < 1; i++)
{
sStringArray = aInfos[i].Split('*');
sStringArray[0] = sStringArray[0].Replace("'", "'");
aLinks.Add(sStringArray[0]);
}
await DownloadFile(aLinks[FilesDownloaded]); // Should really be called "DownloadFileAsync"
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Debug message: " + ex.Message + "InnerEx: " + ex.StackTrace);
Console.WriteLine("Runs: " + Runs);
return;
}
}
I am trying to implement locking scenario where same file is accessed by multiple threads at same time or at different time. While testing it seems code is overwriting the existing line instead of appending new line.
namespace SMPPService
{
public static class LogFile
{
public static void WriteErrorLog(Exception ex)
{
byte[] buf = GetBytes(DateTime.Now.ToString() + ": " + ex.Source.ToString().Trim() + "; " + ex.Message.ToString().Trim());
Lock(HttpRuntime.AppDomainAppPath + "\\Exceptions.txt",
(f) =>
{
try
{
f.Write(buf, 0, buf.Length);
}
catch (IOException ioe)
{
// handle IOException
}
}, buf);
}
public static void WriteErrorLog(string Message)
{
byte[] buf = GetBytes(DateTime.Now.ToString() + ": " + Message);
Lock(HttpRuntime.AppDomainAppPath + "\\LogFile.txt",
(f) =>
{
try
{
f.Write(buf, 0, buf.Length);
}
catch (IOException ioe)
{
// handle IOException
}
}, buf);
System.Threading.Thread.Sleep(60000);
}
public static void Lock(string path, Action<FileStream> action,byte [] lines)
{
var autoResetEvent = new AutoResetEvent(false);
while (true)
{
try
{
using (var file = File.Open(path,
FileMode.OpenOrCreate,
FileAccess.ReadWrite,
FileShare.Write))
{
action(file);
break;
}
}
catch (IOException)
{
var fileSystemWatcher =
new FileSystemWatcher(Path.GetDirectoryName(path))
{
EnableRaisingEvents = true
};
fileSystemWatcher.Changed +=
(o, e) =>
{
if (Path.GetFullPath(e.FullPath) == Path.GetFullPath(path))
{
autoResetEvent.Set();
}
};
autoResetEvent.WaitOne();
}
}
}
static byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
}
}
Usage
LogFile.WriteErrorLog("Requesting SMPP Client from WMAS..." + " " + "Date:" + DateTime.Now + " " + "Source Address:" + msisdn);
FileShare.Write
From MSDN:
Allows subsequent opening of the file for writing.
This is exactly the flag you do not want to use. With files the easiest way to do locking is to let the file system do it for you, use FileShare.Read (so someone can look at the log) and retry if the open fails do to a sharing violation.
Implementing your own locking like that is only going to be re-creating when the file system already does, but badly.
Also, rather than messing handling encoding yourself (getting the edge cases right is not easy):
Open as a text file with a specified encoding (UTF-8 would be my choice).
Open the file for append, so new content will always be written at the end.
There is an overload of StreanWriter's constructor that does this.
EDIT: A quick check of the reference source: this does use FileShare.Read.
You should use File.AppendAllLines instead your lock method. File.AppendAllLines is not Thread safe and you have to lock it.
private object lockObject = new object();
private string fileName = Path.Combine(HttpRuntime.AppDomainAppPath, "LogFile.txt");
public static void WriteErrorLog(string Message)
{
lock(lockObject)
{
File.AppendAllLines(fileName, new string[] { Message + "\n" });
}
}
note that File.AppendAllLines was introduced in .Net 4 and you have to use File.AppendAllText in older framework