Problem regarding downloading files in folders and subfolders - c#

I am stuck and asking for your help, trying to make a software that check a txt file which is this format with CRC information and download the files inside that txt. These is just an example with same hash but in reality have different name, hash and size.
[FOLDER/FILE] [HASH] [FILESIZE]
./file1.dat f926038f 54
./Folder/file2.dat f926038f 54
./Folder/Subfolder/file3.dat f926038f 54
after I generate this type of information, I use this code to read where is the file...
private static void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
StreamReader streamReader = new StreamReader(new WebClient().OpenRead(Import.ServerURL + Import.PatchlistName));
while (!streamReader.EndOfStream)
ListProcessor.AddFile(streamReader.ReadLine());
}
and these code to check the list of that file and write them in current folder
internal class ListProcessor
{
public static void AddFile(string File) => Import.Files.Add(new Import.File()
{
Name = File.Split(' ')[0],
Hash = File.Split(' ')[1],
Size = Convert.ToInt64(File.Split(' ')[2])
});
}
the problem is that files outside of any folders or subfolders they are downloading perfectly, but inside any folder or subfolder the download does not work.
PS: This is the order from where it starts:
Main.cs
private void Btn_Run_Click(object sender, EventArgs e)
{
if (!this.Btn_Run.Enabled)
return;
ListDownloader.DownloadList();
}
ListDownloader.cs
internal class ListDownloader
{
public static void DownloadList()
{
Common.ChangeStatus("LISTDOWNLOAD");
Common.DisableStart();
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += new DoWorkEventHandler(ListDownloader.backgroundWorker_DoWork);
backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(ListDownloader.backgroundWorker_RunWorkerCompleted);
if (backgroundWorker.IsBusy)
{
int num = (int) MessageBox.Show(Texts.GetText("UNKNOWNERROR", (object) "DownloadList isBusy"));
Application.Exit();
}
else
backgroundWorker.RunWorkerAsync();
}
private static void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
StreamReader streamReader = new StreamReader(new WebClient().OpenRead(Import.ServerURL + Import.PatchlistName));
while (!streamReader.EndOfStream)
ListProcessor.AddFile(streamReader.ReadLine());
}
private static void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
FileChecker.CheckFiles();
}
}
FileChecker.cs
internal class FileChecker
{
private static BackgroundWorker backgroundWorker = new BackgroundWorker();
public static void CheckFiles()
{
FileChecker.backgroundWorker.WorkerReportsProgress = true;
FileChecker.backgroundWorker.DoWork += new DoWorkEventHandler(FileChecker.backgroundWorker_DoWork);
FileChecker.backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(FileChecker.backgroundWorker_ProgressChanged);
FileChecker.backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(FileChecker.backgroundWorker_RunWorkerCompleted);
if (FileChecker.backgroundWorker.IsBusy)
{
int num = (int) MessageBox.Show(Texts.GetText("UNKNOWNERROR", (object) "CheckFiles isBusy"));
Application.Exit();
}
else
FileChecker.backgroundWorker.RunWorkerAsync();
}
private static void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
foreach (Import.File file in Import.Files)
{
Import.fullSize += file.Size;
FileChecker.backgroundWorker.ReportProgress(0, (object) Path.GetFileName(file.Name));
if (!System.IO.File.Exists(file.Name) || string.Compare(Common.GetHash(file.Name), file.Hash) != 0)
{
Import.OldFiles.Add(file.Name);
}
else
{
Import.completeSize += file.Size;
FileChecker.backgroundWorker.ReportProgress(1);
}
}
}
private static void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.ProgressPercentage == 0)
{
Common.ChangeStatus("CHECKFILE", e.UserState.ToString());
}
else
{
Common.UpdateCompleteProgress(Computer.Compute(Import.completeSize));
Common.UpdateCurrentProgress(Computer.Compute(Import.completeSize), 0.0);
}
}
private static void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
FileDownloader.DownloadFile();
}
private enum State
{
REPORT_NAME,
REPORT_PROGRESS,
}
}
and FileDownloader.cs
internal class FileDownloader
{
private static int curFile;
private static long lastBytes;
private static long currentBytes;
private static Stopwatch stopWatch = new Stopwatch();
public static void DownloadFile()
{
if (Import.OldFiles.Count <= 0)
{
Common.ChangeStatus("CHECKCOMPLETE");
Common.UpdateCurrentProgress(100L, 0.0);
Common.UpdateCompleteProgress(100L);
Starter.Start();
}
else if (FileDownloader.curFile >= Import.OldFiles.Count)
{
Common.ChangeStatus("DOWNLOADCOMPLETE");
Common.UpdateCurrentProgress(100L, 0.0);
Common.UpdateCompleteProgress(100L);
Starter.Start();
}
else
{
if (Import.OldFiles[FileDownloader.curFile].Contains("/"))
Directory.CreateDirectory(Path.GetDirectoryName(Import.OldFiles[FileDownloader.curFile]));
WebClient webClient = new WebClient();
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(FileDownloader.webClient_DownloadProgressChanged);
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(FileDownloader.webClient_DownloadFileCompleted);
FileDownloader.stopWatch.Start();
Common.ChangeStatus("DOWNLOADFILE", Import.OldFiles[FileDownloader.curFile]);
webClient.DownloadFileAsync(new Uri(Import.ServerURL + Import.OldFiles[FileDownloader.curFile]), Import.OldFiles[FileDownloader.curFile]);
}
}
private static void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
FileDownloader.currentBytes = FileDownloader.lastBytes + e.BytesReceived;
Common.UpdateCompleteProgress(Computer.Compute(Import.completeSize + FileDownloader.currentBytes));
Common.UpdateCurrentProgress((long) e.ProgressPercentage, Computer.ComputeDownloadSpeed((double) e.BytesReceived, FileDownloader.stopWatch));
}
private static void webClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
FileDownloader.lastBytes = FileDownloader.currentBytes;
Common.UpdateCurrentProgress(100L, 0.0);
++FileDownloader.curFile;
FileDownloader.stopWatch.Reset();
FileDownloader.DownloadFile();
}
}

Related

A new message box appears with each second after it appears

I ran into an issue where i tried displaying a display box after a countdown reached a certain time but for some odd reason it replicates with each second despite it having already passed the initial time it was supposed to appear. This is what i tried to do but now the timer has stopped and the time remaining column has stopped runng.
public partial class Form1 : Form
{
private List<CSession> sessionlist = new List<CSession>();
private TimeSpan workingTimeSpan = new TimeSpan();
private TimeSpan fiveMinutes = new TimeSpan(0,1,0);
private TimeSpan oneSecond = new TimeSpan(0,0,1);
public Form1()
{
InitializeComponent();
timer1.Enabled = true;
timer1.Start();
}
private void label1_Click(object sender, EventArgs e)
{
}
private void AddTime_Click(object sender, EventArgs e)
{
workingTimeSpan += fiveMinutes;
DisplayWorkingTimeSpan();
}
private void DisplayWorkingTimeSpan()
{
TimerLabel.Text = workingTimeSpan.ToString();
}
private void DecreaseTime_Click(object sender, EventArgs e)
{
TimeSpan fiveMinutes = new TimeSpan(0,5,0);
workingTimeSpan -= fiveMinutes;
DisplayWorkingTimeSpan();
}
private void Confirm_Click(object sender, EventArgs e)
{
CSession newSession = new CSession();
if(PasswordText.Text == "")
{
MessageBox.Show("Password not entered");
return;
}
newSession.password = PasswordText.Text;
newSession.purchased_time = workingTimeSpan;
newSession.remaining_time = workingTimeSpan;
newSession.status = "Online";
sessionlist.Add(newSession);
PasswordText.Text = "";
TimerLabel.Text = "";
workingTimeSpan = new TimeSpan();
}
private void DisplayAllSessions()
{
listView1.Items.Clear();
foreach(CSession c in sessionlist)
{
string[] row = { c.password, c.purchased_time.ToString(), c.remaining_time.ToString(), c.status };
ListViewItem i = new ListViewItem(row);
listView1.Items.Add(i);
}
}
private void timer1_Tick(object sender, EventArgs e)
{
foreach(CSession c in sessionlist)
{
if (c.remaining_time.TotalMinutes == 5)
{
timer1.Stop();
MessageBox.Show("Time almost up for client.");
}
if (c.remaining_time.TotalSeconds < 1)
{
c.status = "Offline";
}
if(c.status == "Online")
{
c.remaining_time -= oneSecond;
}
}
DisplayAllSessions();
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Close();
}
}
Add a flag that gets toggled when you display the message, so you won't display it again:
private bool MessageDisplayed = false;
private void timer1_Tick(object sender, EventArgs e)
{
foreach(CSession c in sessionlist)
{
if (c.remaining_time.TotalMinutes == 5 && !MessageDisplayed) // <-- check the flag
{
MessageDisplayed = true;
MessageBox.Show("Time almost up for client.");
}
if (c.remaining_time.TotalSeconds < 1)
{
c.status = "Offline";
}
if(c.status == "Online")
{
c.remaining_time -= oneSecond;
}
}
DisplayAllSessions();
}
Now you can leave the timer running and your message will only appear once.

DownloadProgressChanged get called only after file has been downloaded

Im trying to use the progress bar to track my download, the only problem the progress value changes only after the file is downloaded to the computer and not during its download.
Here is my code, any help will be appreciated.
public void DownloadZaq()
{
using (WebClient zaq = new WebClient())
{
zaq.DownloadProgressChanged += new DownloadProgressChangedEventHandler(Zaq_DownloadProgressChanged);
zaq.DownloadFileCompleted += new AsyncCompletedEventHandler(Zaq_DownloadFileCompleted);
zaq.DownloadFileAsync(new Uri(http://example.com), #"c:\to\111.jpg");
}
}
public void Zaq_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
MessageBox.Show("download completed");
}
public void Zaq_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
I think that DownloadFileAsync is blocking the main thread somehow while checking the DNS. This is what I would try
WebClient zaq;
public void DownloadZaq()
{
zaq = new WebClient();
zaq.DownloadProgressChanged += new DownloadProgressChangedEventHandler(Zaq_DownloadProgressChanged);
zaq.DownloadFileCompleted += new AsyncCompletedEventHandler(Zaq_DownloadFileCompleted);
System.Threading.Tasks.Task.Run(() => // Workaround to allow Async call
{
try
{
zaq.DownloadFileAsync(new Uri(http://example.com), #"c:\to\111.jpg");
}
catch (Exception ex)
{
zag.Dispose();
}
});
}
public void Zaq_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
MessageBox.Show("download completed");
zag.Dispose();
}
public void Zaq_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}

Xamarin - Morse code app usuing the flaslight

I am trying to make a morse code for a college project, what I'm trying to do is use a 2 dimensional array to save the morse code people input to a text file and then be able to load it from the text file, my logic was to was that within the array was this array[morse name][morse input]. what I need to figure out first is how to send data from methods / buttons OBtn_Clicked , LBtn_Clicked, SBtn_Clicked and EndBtn_Clicked to NewMorseBtn_Clicked to add into the array which will then write it out to a text file I've created.
namespace FlashLightApp2018
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MorsePage : ContentPage
{
//bool exitLoop = false;
public MorsePage()
{
InitializeComponent();
}
private async void NewMorseBtn_Clicked(object sender, EventArgs e)
{
bool isTextEmpty = String.IsNullOrEmpty(MorseName.Text);
if (isTextEmpty)
{
}
else
{
OBtn.IsEnabled = true;
LBtn.IsEnabled = true;
SBtn.IsEnabled = true;
EndBtn.IsEnabled = true;
// String morseName = MorseName.Text;
//String[,] morseSave = new String[100,100];
}
//File.WriteAllText(morseName, text);
//while (exitLoop != true)
//{
//}
}
private void LoadMorseBtn_Clicked(object sender, EventArgs e)
{
}
private void PlayMorseBtn_Clicked(object sender, EventArgs e)
{
}
private void OBtn_Clicked(object sender, EventArgs e)
{
}
private void LBtn_Clicked(object sender, EventArgs e)
{
}
private void SBtn_Clicked(object sender, EventArgs e)
{
}
private void EndBtn_Clicked(object sender, EventArgs e)
{
}
}
}
first, declare you data at the class level (outside of a single method) so that it is accessible from throughout your class
string morseData = string.Empty;
then have your different button methods update the data
private void OBtn_Clicked(object sender, EventArgs e)
{
morseData += ".";
}
private void LBtn_Clicked(object sender, EventArgs e)
{
moreseData += "-";
}

C# BackgroundWorker class

Currently im trying to update my progress bar if the background worker reports something, heres my code
Form1.cs
namespace YTD
{
public partial class Form1 : Form
{
private Main app;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
int n;
bool isNumeric = int.TryParse(numberBox.Text, out n);
if (!String.IsNullOrWhiteSpace(emailBox.Text) && !String.IsNullOrWhiteSpace(passBox.Text) && !String.IsNullOrWhiteSpace(numberBox.Text) && isNumeric)
{
this.app = new Main(emailBox.Text, passBox.Text, n, logBox, statusBar, backgroundWorker1);
this.app.startMule();
}
else
{
MessageBox.Show("Please fill out all the form fields", "MuleMaker error");
}
}
}
}
And my Main.cs
namespace YTD.classes
{
public class Main
{
private String email;
private String password;
private int number;
private RichTextBox logBox;
private ProgressBar statusBar;
private BackgroundWorker threadWorker;
public Main(String email, String password, int number, RichTextBox logBox, ProgressBar statusBar, BackgroundWorker threadWorker)
{
// Define some variables
this.email = email;
this.password = password;
this.number = number;
this.logBox = logBox;
this.statusBar = statusBar;
this.threadWorker = threadWorker;
}
public void startMule()
{
// Set progressbar 100% value
statusBar.Maximum = this.number;
if (!threadWorker.IsBusy)
{
threadWorker.RunWorkerAsync();
}
}
private void threadWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 1; i <= 10; i++)
{
// Perform a time consuming operation and report progress.
MessageBox.Show("ye");
System.Threading.Thread.Sleep(500);
threadWorker.ReportProgress(i * 10);
}
}
private void threadWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
statusBar.Increment(1);
}
}
}
Currently I get no errors but the progress bar value is not beeing changed.
Without the background worker i can update my progress bar fine but not while doing an expensive action.
Your posted Code does not reveal, if you registered your functions to the BackgroundWorker Events.
Creating a new BackgrounWorker isn't enough.
Here is an example:
public Class Main
{
public Main( ... )
{
BackgroundWorker worker = new BackgroundWorker()
worker.WorkerReportsProgress = true;
// Register to BackgroundWorker-Events
worker.DoWork += threadWorker_DoWork;
worker.ProgressChanged += threadWorker_ProgressChanged;
}
}
in addition you should tell your ProgressBar to rerender.
private void threadWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
statusBar.Increment(1);
statusBar.Invalidate(true);
}
at least you might want to use the value you have set calling ReportProgress(i * 10).
private void threadWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
statusBar.Value = e.ProgressPercentage;
statusBar.Invalidate(true);
}

Working with Grid using BackgroundWorker

I have a GridControl which I populate using a BackgroundWorker. Then I'm using another BackgroundWorker to perform some calculations on the dataset which is the datasource of the GridControl. As I'm trying to do this a cross thread operation on the GridControl error is thrown. I'm unable to understand that despite not performaing any operation on the gridcontrol itself how the error is generating. (I'm using DevExpress, but that should not change the concept).
Also is there any way I can use one BackgroundWorker to do different work, i.e. make this code more efficient.
Here is my code:-
public partial class MainForm : XtraForm
{
private BackgroundWorker loadworker = new BackgroundWorker();
private BackgroundWorker calcworker = new BackgroundWorker();
private AutoResetEvent resetEvent = new AutoResetEvent(false);
private Database _db = EnterpriseLibraryContainer.Current.GetInstance<Database>("ConnString");
private DataSet ds;
public MainForm()
{
InitializeComponent();
loadworker.DoWork += loadworker_DoWork;
loadworker.RunWorkerCompleted += loadworker_RunWorkerCompleted;
loadworker.ProgressChanged += loadworker_ProgressChanged;
loadworker.WorkerReportsProgress = true;
calcworker.DoWork += calcworker_DoWork;
calcworker.RunWorkerCompleted += calcworker_RunWorkerCompleted;
calcworker.ProgressChanged += calcworker_ProgressChanged;
calcworker.WorkerReportsProgress = true;
}
private void calcworker_DoWork(object sender, DoWorkEventArgs e)
{
int _cnt = 0;
foreach (DataRow dr in ds.Tables[0].Rows)
{
dr["GROSS"] = (decimal)dr["BASIC"] + (decimal)dr["HRA"] + (decimal)dr["DA"];
_cnt += 1;
}
for (int i = 0; i <= _cnt; i++)
{
Thread.Sleep(100);
calcworker.ReportProgress((100 * i) / _cnt);
}
}
private void calcworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.SetState(true);
this.MainInit();
}
private void calcworker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.pgb_DataProgress.Position = e.ProgressPercentage;
}
private void loadworker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.pgb_DataProgress.Position = e.ProgressPercentage;
}
private void loadworker_DoWork(object sender, DoWorkEventArgs e)
{
try
{
DbCommand _cmd = _db.GetSqlStringCommand("SELECT Z.EMP_CODE,Z.BASIC,Z.DA,Z.HRA,CAST(0 AS DECIMAL) GROSS FROM Z000000001 Z");
DataSet _data = _db.ExecuteDataSet(_cmd);
for (int i = 0; i <= 10; i++)
{
Thread.Sleep(500);
loadworker.ReportProgress((100 * i) / 10);
}
e.Result = _data;
}
catch (Exception ex)
{
e.Cancel = true;
}
}
private void loadworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.ds = (DataSet)e.Result;
this.gridControl1.DataSource = ds.Tables[0];
this.SetState(true);
this.MainInit();
}
private void btn_FetchData_Click(object sender, EventArgs e)
{
this.gridControl1.DataSource = null;
this.SetState(false);
loadworker.RunWorkerAsync();
}
private void SetState(bool _state)
{
this.btn_Calculate.Enabled = _state;
this.btn_ClearGrid.Enabled = _state;
this.btn_FetchData.Enabled = _state;
}
private void MainInit()
{
this.pgb_DataProgress.Position = 0;
}
private void btn_ClearGrid_Click(object sender, EventArgs e)
{
this.gridControl1.DataSource = null;
}
private void btn_Calculate_Click(object sender, EventArgs e)
{
if (this.gridControl1.DataSource == null)
{
DevExpress.XtraEditors.XtraMessageBox.Show("Data Not loaded", "Message");
return;
}
else
{
this.SetState(false);
calcworker.RunWorkerAsync();
}
}
}
After you attached the Table as DataSource it belongs to the GUI. Suppose your user alters/deletes a row while your Calc thread is running. All sorts of race conditions might happen.
In short, you cannot access controls on a thread other than UI thread on which they are created. So any control method/property call has to be marshall on the UI thread using Control.Invoke method.
For example, in your case loadworker_RunWorkerCompleted event handler will be invoked on a worker thread and accessing control property will throw an error. You need to modify event handler as
private void loadworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
System.Action a = () => {
this.ds = (DataSet)e.Result;
this.gridControl1.DataSource = ds.Tables[0];
this.SetState(true);
this.MainInit();
};
this.gridControl1.Invoke(a);
}

Categories

Resources