I have a problem that I wrote an application that would iterate through files and add +1 to the integer each file, until it reaches a specific file name. The problem is probably because .Net does not access the native file system directly, it fills up collections, but in my case it would take years, believe me, I have 260 000 files in the target folder. The iteration does not even reach the second file. The thread just totally freezes, no errors, no exceptions. So is there any way to get a direct access to the Native File System without any useless collection filling ups?
Here is my code:
private void button1_Click(object sender, EventArgs e)
{
try
{
foreach (string file in Directory.GetFiles("\\\\Mypcname-PC\\vxheaven\\malware"))
{
count++;
label1.Text = Convert.ToString(count);
if (file.Contains(textBox1.Text))
{
label1.Text = Convert.ToString(count) + " reached the file";
break;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
btw. Sorry for my bad english
Regards
Because you are doing all the work on the UI thread it can't refresh while it is working. You need to do the work on a background thread then update the UI in a thread safe way. Also switching to Directory.EnumerateFiles will make it faster to read the first file so it does not need to store all the records in to an array. Lastly I changed ex.Message to ex.ToString(), it will display much more useful information that way.
private async void button1_Click(object sender, EventArgs e)
{
try
{
var text = textBox1.Text;
var progress = new Progress<string>((x) => label1.Text = x);
await Task.Run(() => DoWork(progress, text));
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void DoWork(IProgress<string> progress, string text)
{
foreach (string file in Directory.EnumerateFiles("\\\\Mypcname-PC\\vxheaven\\malware"))
{
count++;
progress.Report(Convert.ToString(count));
if (file.Contains(text))
{
progress.Report(Convert.ToString(count) + " reached the file");
break;
}
}
}
(Code was written in a web browser from memory so there may be errors)
Seems like you are using a potentially very time-consuming loop without ever processing the Windows message queue, therefore your application may APPEAR to be frozen, while it's probably just busy doing what you instructed it to do in the loop. Try this:
private void button1_Click(object sender, EventArgs e)
{
try
{
foreach (string file in Directory.GetFiles("\\\\Mypcname-PC\\vxheaven\\malware"))
{
count++;
label1.Text = Convert.ToString(count);
Application.DoEvents();
if (file.Contains(textBox1.Text))
{
label1.Text = Convert.ToString(count) + " reached the file";
break;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Related
I'm trying to download audio from youtube using YoutubeExtractor but if click the button i have information "sequence has no elements". How i can solve it?
private void button2_Click(object sender, EventArgs e)
{
try
{
IEnumerable<VideoInfo> videos = DownloadUrlResolver.GetDownloadUrls(textBox1.Text);
VideoInfo video = videos.Where(info => info.CanExtractAudio).OrderByDescending(info => info.AudioBitrate).First();
if (video.RequiresDecryption)
{
DownloadUrlResolver.DecryptDownloadUrl(video);
}
AudioDownloader download = new AudioDownloader(video, Path.Combine(Application.StartupPath + "\\", video.Title + video.AudioExtension));
download.Execute();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
The issues is the call to First(). This will throw an exception if your IEnumerable contains no items.
To correct this, you need to be sure of two things:
The DownloadUrlResolver.GetDownloadUrls() function returns at least 1 item.
That at least one item in the videos variable has CanExtractAudio set to true.
I already have the saving part down and I know it works, but when I click load button, it will not display anything that I have saved from the text boxes that go to the saying.txt file
using System;
using System.IO;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Grades : Form
{
private StreamWriter fil;
public Grades()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
fil = new StreamWriter("saying.txt"); //This is the txt file
}
catch (DirectoryNotFoundException exc)
{
lstBxDisplay.Text = "Nothing " +
exc.Message;
}
catch (System.IO.IOException exc)
{
lstBxDisplay.Text = exc.Message;
}
}
// saving the files to the saying.txt
private void btnSaveAs_Click(object sender, EventArgs e)
{
try
{
fil.WriteLine(txtBxLastName.Text);
txtBxLastName.Text = "";
txtBxLastName.Focus();
}
catch (System.IO.IOException exc)
{
lstBxDisplay.Text = exc.Message;
}
}
// next is the load button to load the files into the list/display box
private void btnLoad_Click(object sender, EventArgs e)
{
string inValue;
try
{
using (StreamReader infil =
new StreamReader("saying.txt"))
{
inValue = infil.ReadLine();
while (inValue != null)
{
inValue = infil.ReadLine();
if (inValue != null)
this.lstBxDisplay.Items.Add(inValue);
} // end of while
} // end of using
}
catch (System.IO.IOException exc)
{
lstBxDisplay.Text = exc.Message;
}
}
private void Grades_FormClosing(object sender, FormClosingEventArgs e)
{
try
{
fil.Close();
}
catch
{
}
}
}
}
any reason why it is not loading into the list box? I have tried both label and text box to display the message and neither of them work. I debugged the program and it is executing fine
You have multiple issues here but I will point out two main issues that will get your code working.
You are not closing the stream when you try to save. If the stream stays open, you will never be able to read the values when you try to "Load" the file. You need to call fil.Close(); at the end of your btnSaveAs_Click method.
This is how the save should read.
fil.WriteLine(txtBxLastName.Text);
txtBxLastName.Text = "";
txtBxLastName.Focus();
fil.Close();
You're skipping the first line of the file in your "Load" method. You call infil.ReadLine(); then in the loop, you call it again before you add it to your listbox. You need to move your second ReadLine(). If you are only ever writing a single line to the file, your existing code will skip that first line and try to read it again which will be null (no second line). So, it will never add anything to your listbox.
This is how the reads should be ordered.
using (StreamReader infil = new StreamReader("saying.txt"))
{
inValue = infil.ReadLine();
while (inValue != null)
{
this.lstBxDisplay.Items.Add(inValue);
inValue = infil.ReadLine();
} // end of while
} // end of using
Those changes will get you working. Now to point out, you are going about reading and writing to a file all wrong. You should not be opening a stream in your form load and waiting for button clicks to be writing/reading from that stream. Unless you have a very good reason to do what you are doing, you should be opening your stream, performing the read/write operation, and closing your stream right away. For a simple file IO, I would even suggest using a different mechanism. Look at the MSDN for the System.IO.File Class for easier methods to read lines or write lines to a file.
I'm working on a wp8-app that takes a photo and then takes you to the next screen to decide whether you like it or not.
The current approach was this:
private void ShutterButton_Click(object sender, RoutedEventArgs e)
{
if (cam != null)
{
try
{
cam.CaptureImage();
await Task.Delay(1500);
NavigateFront();
}
catch (Exception ex)
{
...
}
}
}
public void NavigateFront()
{
string naviString = "/confirmPicture.xaml?parameter=" + fileName.ToString();
_rootFrame.Navigate(new Uri(naviString, UriKind.Relative));
}
On my Lumia 520 it crashed sometimes. If I increase the wait-time to 2,5sec it works. But of course this should not be the way to do it.
If I catch the void cam_CaptureImageAvailable(object sender, Microsoft.Devices.ContentReadyEventArgs e)-Event and try to navigate after everything is done and all streams are closed I still get in a NavigateFailed-State and the app crashes.
My question is: is there any other useful event that ensures that all work is done and I can navigate without using static time-based values?
Navigation with a PhotoCamera is possible, just subscribe to its CaptureCompleted event handler
cam.CaptureCompleted += new EventHandler<CameraOperationCompletedEventArgs>(camera_CaptureCompleted);
and this would be the event
void camera_CaptureCompleted(object sender, CameraOperationCompletedEventArgs e)
{
try
{
Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
try
{
cam.Dispose();
NavigationService.Navigate(new Uri("URI nething", UriKind.Relative));
}
catch (Exception)
{
MessageBox.Show("Problem occured!!");
}
});
}
catch
{
MessageBox.Show("Problem in camer_capturecompleted");
}
}
I did it in one of my apps targeting windows phone 7. Check if this works for you as well.
I have an application that performs a time consuming task when the user selects an item for a listbox.
When a user selects a show the application will retrieve all the shows information form the tvdb and the display it in the Ui.
The problem occurs when a user quickly changes selection while the show is still loading.
I would like to make it so that a user could change their mind and then make another selection while the first was loading and have that information displayed in the Ui.
I have created a simple demonstration application to show the problem : Demo App .
This is what i tried to do
List box selection event handler
private void lb1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string sid = lb1.SelectedItem.ToString();
try
{
LoadSeries(Int32.Parse(sid));
}
catch (FormatException)
{
MessageBox.Show("Please enter a valid series id");
}
}
LoadSeries
private void LoadSeries(int _seriesId)
{
Task<TvdbSeries> series = Task.Factory.StartNew(() =>
{
TvdbSeries seriesloaded = null;
try
{
seriesloaded = m_tvdbHandler.GetSeries(_seriesId, TvdbLanguage.DefaultLanguage, true, true, true, true);
}
catch (TvdbInvalidApiKeyException ex)
{
MessageBox.Show(ex.Message);
}
catch (TvdbNotAvailableException ex)
{
MessageBox.Show(ex.Message);
}
return seriesloaded;
}
);
series.ContinueWith((antecedent) =>
{
UpdateSeries(series.Result);
},
TaskScheduler.FromCurrentSynchronizationContext()
);
}
If a user changes selection quickly the application errors on the line seriesloaded = m_tvdbHandler.GetSeries(_seriesId, TvdbLanguage.DefaultLanguage, true, true, true, true); and shows this message in the debugger "WebClient does not support concurrent I/O operations."
I did find out that it is because I am making a new request before the last one is finished but I have no way of chaining the code in m_tvdbHandler.GetSeries because its functionality comes from library i am using and some one else wrote .
This is the library tvdblib , I am sure the problem is with how I am doing things and not the library .
when a user makes a selection you can disable the UI till the information is loaded completely and display a message at the bottom loading please wait. Once everything is loaded, enable the Ui and hide the message.
You are posting this question as a C#5.0 question, so you should be using async/await as much as you can.
private Task<TvdbSeries> LoadSeriesAsync(int _seriesId)
{
return Task.Run(() =>
{
TvdbSeries seriesloaded = null;
try
{
seriesloaded = m_tvdbHandler.GetSeries(_seriesId, TvdbLanguage.DefaultLanguage, true, true, true, true);
}
catch (TvdbInvalidApiKeyException ex)
{
MessageBox.Show(ex.Message);
}
catch (TvdbNotAvailableException ex)
{
MessageBox.Show(ex.Message);
}
return seriesloaded;
}
);
}
It would be much better if there was a LoadSeriesAsync.
One way to do it would be to disable lb1 while retrieving the series.
private async void lb1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string sid = lb1.SelectedItem.ToString();
try
{
lb1.IsEnabled = false;
var series = await LoadSeriesAsync(Int32.Parse(sid));
UpdateSeries(series);
}
catch (FormatException)
{
MessageBox.Show("Please enter a valid series id");
lb1.IsEnabled = true;
}
}
Here's the code for the event handler involved:
private void textBox1_TextChanged(object sender, EventArgs e)
{
try
{
seed = Convert.ToInt32(this.Text);
}
catch (FormatException)
{
MessageBox.Show("Input string is not a sequence of digits.");
}
catch (OverflowException)
{
MessageBox.Show("The number cannot fit in an Int32.");
}
}
It's supposed to ensure a user doesn't type anything but a number allowable by Int32 into the text box, but the first catch statement executes EVERY time you try to type ANYTHING into the box. I've looked around but I can't seem to figure out why...
Probably because this.Text doesn't read from the input box, but rather the class the handler is defined in.
I believe what you want is:
try
{
seed = Convert.ToInt32(((TextBox)caller).Text);
}
It might be helpful to see the error message, using the following (temporarily of course):
catch (FormatException exception)
{
MessageBox.Show("Input string is not a sequence of digits."
+ "Exception message was: " + exception.getMessage());
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
try
{
seed = Convert.ToInt32(textBox1.text);
}
catch (FormatException)
{
MessageBox.Show("Input string is not a sequence of digits.");
}
catch (OverflowException)
{
MessageBox.Show("The number cannot fit in an Int32.");
}
}
Please use the above statement and it should work correctly. If you type in a number the first exception will not execute.