Within OnCreate()
new Thread(new ThreadStart(() => {
this.RunOnUiThread(async () =>
{
await SetData(TodaysDate); ;
//await FindNotesForDay(TodaysDate, TodaysDate.AddDays(+6));
progress.Dismiss();
});
})).Start();
private async Task SetData(DateTime date)
{
await Task.Run(() =>
{
dicMyMap = null;
dicMyMap = new Dictionary<string, List<ClassInstance>>();
List<string> group = new List<string>();
group.Add("Monday");
group.Add("Tuesday");
group.Add("Wednesday");
group.Add("Thursday");
group.Add("Friday");
dicMyMap.Add(group[0], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));
date = date.AddDays(+1);
dicMyMap.Add(group[1], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));
date = date.AddDays(+1);
dicMyMap.Add(group[2], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));
date = date.AddDays(+1);
dicMyMap.Add(group[3], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));
date = date.AddDays(+1);
dicMyMap.Add(group[4], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));
myAdapater = new ExpandableListViewAdapter(this, group, dicMyMap);
expandableListView.SetAdapter(myAdapater);
});
}
private List<ClassInstance> ListsPopulation(String date)
{
string sql = "SELECT * FROM lectures join groupConvert using (Groups) where StartDate = '" + date + "' AND Cohort = '" + User.Cohort + "' AND Year = '" + User.IntakeYear + "';";
List<ClassInstance> Temp = new List<ClassInstance>();
//Insert Header
Temp.Add(new ClassInstance("Start Time", "End Time", "Subject", "Location", "", ""));
using (MySqlCommand cmd = new MySqlCommand(sql, Connect.GetConnection()))
{
MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
ClassInstance c = new ClassInstance(reader["StartTime"].ToString(), reader["EndTime"].ToString(), reader["Theme"].ToString(), reader["Location"].ToString(), reader["Essential"].ToString(), reader["Notes"].ToString());
Temp.Add(c);
}
}
if (Temp.Count == 1)
{
Temp.Clear();
Temp.Add(new ClassInstance("No Classes", "", "", "", "", ""));
}
return Temp;
}
Hello
I am currently attempting to populate a ListView from a database hosted on AWS. As you can imagine It takes a bit of time to load. My issue is my current code is throwing an error. The error thrown is ambiguous and not helpful just states the program has crashed.
In essence what i want to do is quite simple, I basically want to just display a dialog while these methods are loading.
Any advice regarding my code would be excellent.
Edit: I have narrowed the error message down to this area of the code. Prior to attempting to use threads I was able to load this Activity however due to the fact there wasn't a loading message it would appear to the user that the activity had frozen rather than the fact it was loading.
Thanks,
Joe
So i managed to fix the code above to run correctly.
If you have any feedback or comments let me know and i hope someone finds this helpful.
I was using the Async methods completely incorrectly, you are also unable to call a Async method from the oncreate as i'm sure you are aware. Part of my solution was to change all the methods which i had made Async incorrectly back to void (Meaning they were synchronous).
I then created a thread to run the commands and they are now finally running in the correct order :).
Its important to note within the Thread any elements affected by the UI will required them to be run using the main UI thread, this applies to the methods they called as well.
Below is the area of code which i created to fix the issue i had
// Try catch attempt to catch all errors, the error dialog thrown within
//the catch is fairly simple
try
{
//Start loading spinner
var LoadingProgressDialog = ProgressDialog.Show(this, "Loading", "Loading", false);
//Start loading thread, this thread will carry out the functions
// in the order you requested
Thread LoadingThread = new Thread(() =>
{
//Line below only relevant to my code
StartMonday.Text = "Week Commencing On " + TodaysDate.ToLongDateString();
// Call this method first
SetData(TodaysDate);
// call this method second
FindNotesForWeek(TodaysDate, 7);
//Update the UI on the main thread but call third this will close the loading dialog message
RunOnUiThread(() => LoadingProgressDialog.Hide());
// End of thread
});
//Run the thread
LoadingThread.Start();
}
catch (Exception e)
{
var ErrorMessageDialog = ProgressDialog.Show(this, "Loading", e.ToString(), false);
}
Below is my complete class for reference for another user. I have not doced this code as its large enough within this comment
namespace MedicalHubApplication
{
[Activity(Label = "TimeTable", NoHistory = true)]
public class TimeTable : Activity
{
ClassInstance populateClass = new ClassInstance();
UserInstance User = new UserInstance();
GetConnectionClass Connect = new GetConnectionClass();
Dictionary<string, List<ClassInstance>> dicMyMap;
TextView DateHeaderTV;
TextView NoteHeaderTV;
ExpandableListViewAdapter myAdapater;
ExpandableListView expandableListView;
// Need Instance of List
NotesListViewAdapter myNoteAdapater;
ListView NotesListView;
ScrollView ScrollViewList;
TextView StartMonday;
Button SelectDateButton;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your application here
SetContentView(Resource.Layout.TimeTable);
expandableListView = FindViewById<ExpandableListView>(Resource.Id.ListViewExpanded);
StartMonday = FindViewById<TextView>(Resource.Id.TextViewStartDateMonday);
SelectDateButton = FindViewById<Button>(Resource.Id.SelectDateButton);
NotesListView = FindViewById<ListView>(Resource.Id.NotesListView);
DateHeaderTV = FindViewById<TextView>(Resource.Id.DateHeader);
NoteHeaderTV = FindViewById<TextView>(Resource.Id.NoteHeader);
ScrollViewList = FindViewById<ScrollView>(Resource.Id.ScrollView);
// Populate User
User = JsonConvert.DeserializeObject<UserInstance>(Intent.GetStringExtra("User"));
//Find Monday
DateTime TodaysDate = DateTime.Now;
while (TodaysDate.DayOfWeek != DayOfWeek.Monday) TodaysDate = TodaysDate.AddDays(-1);
try
{
var LoadingProgressDialog = ProgressDialog.Show(this, "Loading", "Loading", false);
Thread LoadingThread = new Thread(() =>
{
StartMonday.Text = "Week Commencing On " + TodaysDate.ToLongDateString();
SetData(TodaysDate);
FindNotesForWeek(TodaysDate, 7);
RunOnUiThread(() => LoadingProgressDialog.Hide());
});
LoadingThread.Start();
}
catch (Exception e)
{
var ErrorMessageDialog = ProgressDialog.Show(this, "Loading", e.ToString(), false);
}
SelectDateButton.Click += delegate
{
DateSelectOnClick();
};
}
private void DateSelectOnClick()
{
DatePickerFragment frag = DatePickerFragment.NewInstance(delegate (DateTime SelectedDate)
{
while (SelectedDate.DayOfWeek != DayOfWeek.Monday) SelectedDate = SelectedDate.AddDays(-1);
try
{
var LoadingProgressDialog = ProgressDialog.Show(this, "Loading", "Loading", false);
Thread LoadingThread = new Thread(() =>
{
RunOnUiThread(() => StartMonday.Text = "Week Commencing On " + SelectedDate.ToLongDateString());
SetData(SelectedDate);
FindNotesForWeek(SelectedDate, 7);
RunOnUiThread(() => LoadingProgressDialog.Hide());
});
LoadingThread.Start();
}
catch (Exception e)
{
var ErrorMessageDialog = ProgressDialog.Show(this, "Loading", e.ToString(), false);
}
});
frag.Show(FragmentManager, DatePickerFragment.TAG);
}
private void SetData(DateTime date)
{
dicMyMap = null;
dicMyMap = new Dictionary<string, List<ClassInstance>>();
List<string> group = new List<string>();
group.Add("Monday");
group.Add("Tuesday");
group.Add("Wednesday");
group.Add("Thursday");
group.Add("Friday");
dicMyMap.Add(group[0], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));
date = date.AddDays(+1);
dicMyMap.Add(group[1], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));
date = date.AddDays(+1);
dicMyMap.Add(group[2], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));
date = date.AddDays(+1);
dicMyMap.Add(group[3], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));
date = date.AddDays(+1);
dicMyMap.Add(group[4], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));
myAdapater = new ExpandableListViewAdapter(this, group, dicMyMap);
RunOnUiThread(() => expandableListView.SetAdapter(myAdapater));
}
private List<ClassInstance> ListsPopulation(String date)
{
string sql = "SELECT * FROM lectures join groupConvert using (Groups) where StartDate = '" + date + "' AND Cohort = '" + User.Cohort + "' AND Year = '" + User.IntakeYear + "';";
List<ClassInstance> Temp = new List<ClassInstance>();
//Insert Header
Temp.Add(new ClassInstance("Start Time", "End Time", "Subject", "Location", "", ""));
using (MySqlCommand cmd = new MySqlCommand(sql, Connect.GetConnection()))
{
MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
ClassInstance c = new ClassInstance(reader["StartTime"].ToString(), reader["EndTime"].ToString(), reader["Theme"].ToString(), reader["Location"].ToString(), reader["Essential"].ToString(), reader["Notes"].ToString());
Temp.Add(c);
}
}
if (Temp.Count == 1)
{
Temp.Clear();
Temp.Add(new ClassInstance("No Classes", "", "", "", "", ""));
}
return Temp;
}
private void FindNotesForWeek(DateTime StartDate, int DaysInMonth)
{
List<NotesInstance> WeekNotes = new List<NotesInstance>();
WeekNotes.AddRange(FindNotesForDay(StartDate, StartDate.AddDays(+DaysInMonth)));
if (WeekNotes.Count != 0)
{
RunOnUiThread(() => NoteHeaderTV.Visibility = ViewStates.Visible);
RunOnUiThread(() => NotesListView.Visibility = ViewStates.Visible);
RunOnUiThread(() => DateHeaderTV.Text = "Date:");
myNoteAdapater = new NotesListViewAdapter(this, WeekNotes);
RunOnUiThread(() => NotesListView.Adapter = myNoteAdapater);
}
else
{
RunOnUiThread(() => NoteHeaderTV.Visibility = ViewStates.Invisible);
RunOnUiThread(() => NotesListView.Visibility = ViewStates.Invisible);
RunOnUiThread(() => DateHeaderTV.Text = "No Notifications");
}
// Set up Adapter
myNoteAdapater = new NotesListViewAdapter(this, WeekNotes);
RunOnUiThread(() => NotesListView.Adapter = myNoteAdapater);
}
private List<NotesInstance> FindNotesForDay(DateTime StartDate, DateTime EndDate)
{
string sql = "SELECT * FROM Notes WHERE dates between '" + StartDate.ToString("yyyy-MM-dd") + "' AND '" + EndDate.ToString("yyyy-MM-dd") + "' AND yearGroup = '" + User.IntakeYear.ToString() + "';";
List<NotesInstance> Temp = new List<NotesInstance>();
using (MySqlCommand cmd = new MySqlCommand(sql, Connect.GetConnection()))
{
MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
NotesInstance c = new NotesInstance(reader.GetDateTime("dates").ToString("dd-MM-yyyy"), reader["Notes"].ToString());
Temp.Add(c);
}
}
return Temp;
}
}
}
Related
I am working on EF. I am trying to insert into a table, the insert function is in a thread.
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
int bytes = port.BytesToRead;
//string indata = sp.ReadExisting();
Thread.Sleep(50);
try
{
receivedBytes = port.BaseStream.Read(buffer, 0, (int)buffer.Length);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message.ToString());
}
var receiveData = BitConverter.ToString(buffer, 0, receivedBytes);
var finalData = receiveData.Replace("-", "");
//Thread.Sleep(100);
Console.WriteLine("Thread Going to Start");
new Thread(() => {
SaveData(finalData);
}).Start(); // starting the thread
port.DiscardOutBuffer();
port.DiscardInBuffer();
}
And this is my save data function
public void SaveData(string finalData)
{
Console.WriteLine(LineNumber() + "Data Transmiting...");
thread = Thread.CurrentThread;
mdc_dbEntities e = new mdc_dbEntities();
var msn = e.mdc_meter_config.Where(m => m.m_hex == sr).Select(s => new { s.msn, s.p_id, s.meter_id }).ToList();
var H = finalData.Substring(0, 2);
using (mdc_dbEntities u = new mdc_dbEntities())
{
foreach (var res in msn)
{
var cust_id = e.mdc_meter_cust_rel.Where(m => m.msn == res.msn)
.Select(s => s.cust_id)
.FirstOrDefault();
mdc_meters_data data = new mdc_meters_data()
{
msn = res.msn,
cust_id = cust_id,
device_id = res.meter_id.ToString(),
kwh = e_val.ToString(),
voltage_p1 = a_vol_val.ToString(),
voltage_p2 = b_vol_val.ToString(),
voltage_p3 = c_vol_val.ToString(),
current_p1 = a_curr_val.ToString(),
current_p2 = b_curr_val.ToString(),
current_p3 = c_curr_val.ToString(),
data_date_time = Convert.ToDateTime(theDate.ToString(format)),
d_type = d_type.ToString(),
pf1 = a_pf_val.ToString(),
pf2 = b_pf_val.ToString(),
pf3 = c_pf_val.ToString(),
p_id = res.p_id,
};
u.mdc_meters_data.Add(data);
}
u.SaveChanges();
}
Console.WriteLine(LineNumber() + "Data Saved");
Thread.Sleep(50);
}
try
{
thread.Abort(); // aborting it after insertion
//Thread.Sleep(50);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message.ToString());
}
}
The above code runs for some time, but after that I encountered an error at u.SaveChanges();
System.Data.Entity.Core.EntityException: 'An error occurred while closing the provider connection. See the inner exception for details.'
MySqlException: Fatal error encountered during command execution.
MySqlException: Fatal error encountered attempting to read the resultset.
MySqlException: Reading from the stream has failed.
IOException: Unable to read data from the transport connection: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
I have looked into each solution and tried them but still unable to resolve this issue. I must be missing something that I don't know.
Update 1 My whole code
Calling constructor
public CommunicationEngine()
{
port.ReadTimeout = 500;
port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
port.Open();
Console.WriteLine("Port opened successfully");
Console.WriteLine("I am Recieving");
}
Calling handler
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
int bytes = port.BytesToRead;
Thread.Sleep(50);
Console.WriteLine("Bytes are ok..." + port.BytesToRead + " Recieved ");
try
{
receivedBytes = port.BaseStream.Read(buffer, 0, (int)buffer.Length);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message.ToString());
}
var receiveData = BitConverter.ToString(buffer, 0, receivedBytes);
var finalData = receiveData.Replace("-", "");
//Thread.Sleep(100);
Console.WriteLine("Thread Going to Start");
try
{
new Thread(() => {
SaveData(finalData);
}).Start();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message.ToString());
}
port.DiscardOutBuffer(); port.DiscardInBuffer();
}
Saving data into DB
public void SaveData(string finalData)
{
Console.WriteLine(LineNumber() + "Data Transmiting...");
thread = Thread.CurrentThread;
if (finalData.Length == 138)
{
comm = true;
var H = finalData.Substring(0, 2);
var FC = finalData.Substring(2, 9);
var len = finalData.Substring(10, 2);
var sr = finalData.Substring(12, 12);
var energy_tag = finalData.Substring(24, 4);
var e_val = hexToDec(finalData.Substring(28, 8)) / 10;
var a_curr_tag = finalData.Substring(36, 4);
var a_curr_val = hexToDec(finalData.Substring(40, 8)) / 1000;
var b_curr_tag = finalData.Substring(48, 4);
var b_curr_val = hexToDec(finalData.Substring(52, 8)) / 1000;
var c_curr_tag = finalData.Substring(60, 4);
var c_curr_val = hexToDec(finalData.Substring(64, 8)) / 1000;
var a_vol_tag = finalData.Substring(72, 4);
var a_vol_val = hexToDec(finalData.Substring(76, 8)) / 10;
var b_vol_tag = finalData.Substring(84, 4);
var b_vol_val = hexToDec(finalData.Substring(88, 8)) / 10;
var c_vol_tag = finalData.Substring(96, 4);
var c_vol_val = hexToDec(finalData.Substring(100, 8)) / 10;
var a_pf_tag = finalData.Substring(108, 4);
var a_pf_val = hexToDec(finalData.Substring(112, 4)) / 1000;
var b_pf_tag = finalData.Substring(116, 4);
var b_pf_val = hexToDec(finalData.Substring(120, 4)) / 1000;
var c_pf_tag = finalData.Substring(124, 4);
var c_pf_val = hexToDec(finalData.Substring(128, 4)) / 1000;
var crc = finalData.Substring(132, 4);
var ftr = finalData.Substring(136, 2);
var d_type = "600";
DateTime theDate = DateTime.Now;
string format = "yyyy-MM-dd HH:mm:ss";
Console.WriteLine(LineNumber() + "Data Ready to be inserted in DB");
using (mdc_dbEntities u = new mdc_dbEntities())
{
var msnList = u.mdc_meter_config.Where(m => m.m_hex == sr)
.Select(s => new { s.msn, s.p_id, s.meter_id })
.ToList();
foreach (var res in msnList)
{
var cust_id = u.mdc_meter_cust_rel.Where(m => m.msn == res.msn)
.Select(s => s.cust_id)
.FirstOrDefault();
mdc_meters_data data = new mdc_meters_data()
{
msn = res.msn,
cust_id = cust_id,
device_id = res.meter_id.ToString(),
kwh = e_val.ToString(),
voltage_p1 = a_vol_val.ToString(),
voltage_p2 = b_vol_val.ToString(),
voltage_p3 = c_vol_val.ToString(),
current_p1 = a_curr_val.ToString(),
current_p2 = b_curr_val.ToString(),
current_p3 = c_curr_val.ToString(),
data_date_time = Convert.ToDateTime(theDate.ToString(format)),
d_type = d_type.ToString(),
pf1 = a_pf_val.ToString(),
pf2 = b_pf_val.ToString(),
pf3 = c_pf_val.ToString(),
p_id = res.p_id,
};
u.mdc_meters_data.Add(data);
}
try
{
u.SaveChanges();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message.ToString());
}
}
Console.WriteLine(LineNumber() + "Data Saved");
Thread.Sleep(50);
}
else if(finalData.Length == 30)
{
var msn_no = finalData.Substring(12, 12);
mdc_dbEntities p = new mdc_dbEntities();
var update = p.meter_control.Where(c => (c.comm_executed == 0))
.Where(o => (o.m_hex == msn_no))
.SingleOrDefault();
if(update.comm_sent == "Disconnect")
{
update.comm_executed = 1;
update.comm = 0;
p.SaveChanges();
Console.WriteLine("Meter Disconnected....");
}
else if(update.comm_sent == "Connect")
{
update.comm_executed = 1;
update.comm = 1;
p.SaveChanges();
Console.WriteLine("Meter Connected....");
}
comm = true;
}
else
{
comm = true;
}
try
{
thread.Abort();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message.ToString());
}
}
Any help would be highly appreciated.
Executing EF related changes in a manually initiated thread is not a good idea. Try to run the EF changes in the same thread. If you are bothered with processing incoming requests, use Async, and Await feature. I have modified your code to accommodate this feature. Please try this.
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
int bytes = port.BytesToRead;
//string indata = sp.ReadExisting();
try
{
receivedBytes = port.BaseStream.Read(buffer, 0, (int)buffer.Length);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message.ToString());
}
var receiveData = BitConverter.ToString(buffer, 0, receivedBytes);
var finalData = receiveData.Replace("-", "");
Console.WriteLine("Thread Going to Start");
SaveDataAsync(finalData).Wait(); // this call will become sync and runs under main thread.
port.DiscardOutBuffer();
port.DiscardInBuffer();
}
public async Task<bool> SaveDataAsync(string finalData)
{
mdc_dbEntities e = new mdc_dbEntities();
var msn = e.mdc_meter_config.Where(m => m.m_hex == sr).Select(s => new { s.msn, s.p_id, s.meter_id }).ToList();
var H = finalData.Substring(0, 2);
var isSaveSuccess = false;
using (mdc_dbEntities u = new mdc_dbEntities())
{
foreach (var res in msn)
{
var cust_id = e.mdc_meter_cust_rel.Where(m => m.msn == res.msn)
.Select(s => s.cust_id)
.FirstOrDefault();
mdc_meters_data data = new mdc_meters_data()
{
msn = res.msn,
cust_id = cust_id,
device_id = res.meter_id.ToString(),
kwh = e_val.ToString(),
voltage_p1 = a_vol_val.ToString(),
voltage_p2 = b_vol_val.ToString(),
voltage_p3 = c_vol_val.ToString(),
current_p1 = a_curr_val.ToString(),
current_p2 = b_curr_val.ToString(),
current_p3 = c_curr_val.ToString(),
data_date_time = Convert.ToDateTime(theDate.ToString(format)),
d_type = d_type.ToString(),
pf1 = a_pf_val.ToString(),
pf2 = b_pf_val.ToString(),
pf3 = c_pf_val.ToString(),
p_id = res.p_id,
};
u.mdc_meters_data.Add(data);
}
isSaveSuccess = (await u.SaveChangesAsync())>0; // if records inserted, the count will be more than 0
}
return isSaveSuccess;
}
}
this is easier to read and may help
saying all this please ensure that you can actually make a connection to the db
double check connectionString
public void SaveData(string finalData)
{
Console.WriteLine(LineNumber() + "Data Transmiting...");
using (mdc_dbEntities dbContext = new mdc_dbEntities())
{
var msnList = dbContext.mdc_meter_config.Where(m => m.m_hex == sr)
.Select(s => new { s.msn, s.p_id, s.meter_id })
.ToList();
//put debug point here and check that msnList is populated
foreach (var item in msnList)
{
//this is slow as it will be a db query for each loop
var cust_id = dbContext.mdc_meter_cust_rel.Where(m => m.msn == item.msn)
.Select(s => s.cust_id)
.FirstOrDefault();
var data = new mdc_meters_data()
{
msn = item.msn,
cust_id = cust_id,
device_id = item.meter_id.ToString(),
kwh = e_val.ToString(),
voltage_p1 = a_vol_val.ToString(),
voltage_p2 = b_vol_val.ToString(),
voltage_p3 = c_vol_val.ToString(),
current_p1 = a_curr_val.ToString(),
current_p2 = b_curr_val.ToString(),
current_p3 = c_curr_val.ToString(),
data_date_time = Convert.ToDateTime(theDate.ToString(format)),
d_type = d_type.ToString(),
pf1 = a_pf_val.ToString(),
pf2 = b_pf_val.ToString(),
pf3 = c_pf_val.ToString(),
p_id = item.p_id,
};
dbContext.mdc_meters_data.Add(data);
}
//depending on how many you added this may take some time.
dbContext.SaveChanges();
}
}
I have a c# application using WPF. I have a method notification(); (that show a notification if there is an approaching appointment in my data base) and i want to execute it several time (no stop) in parrallel while my app is running, so that it can check in the data base at every moment!
i search on the net and i try many solution like threading, timer, but it execute it just one time in parrallel !
public partial class MenuPrincipal : Window
{
public MenuPrincipal()
{
InitializeComponent();
UserControl usc = new Menu(ListRDV);
SelectionGrid.Children.Add(usc);
usc.VerticalAlignment = VerticalAlignment.Stretch;
usc.HorizontalAlignment = HorizontalAlignment.Stretch;
WindowStartupLocation = WindowStartupLocation.CenterScreen;
Globals.TempcalculNotif = 60;
Globals.TempRappelRDV = 15;
Thread thrdNotif = new Thread(notification);
thrdNotif.Start();
}
private void notification()
{
MessageBox.Show("calcul notif");
string con = $#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename={System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)}\MCDatabase.mdf;Integrated Security=True";
MCDataClassDataContext dataClass = new MCDataClassDataContext(con);
IQueryable<RendezVous> NotifRdv = (from rendezVous in dataClass.RendezVous
orderby rendezVous.Date
select rendezVous);
int cpt = 0;
if (NotifRdv.Count() != 0)
{
foreach (RendezVous rdv in NotifRdv)
{
string dateRdv, dateAJRD;
dateRdv = rdv.Date.ToString().Substring(0, 10);
dateAJRD = DateTime.Today.ToString().Substring(0, 10);
if (string.Compare(dateRdv, dateAJRD) == 0)
{
DateTime t1 = (DateTime)rdv.Date;
DateTime t2 = DateTime.Now;
TimeSpan t = t2 - t1;
if (t.TotalMinutes < Globals.TempRappelRDV)
{
if (rdv.IdPatient != 0)
{
if (rdv.Important == true)
{
TextBlock TextRDV = new TextBlock();
IQueryable<Patient> patientRDV = (from patient in dataClass.Patient
where rdv.IdPatient == patient.Id
select patient);
IQueryable<Personne> personneRDV = (from personne in dataClass.Personne
where patientRDV.First().IdPersonne == personne.Id
select personne);
string NomPatient = personneRDV.First().nom;
string PrenomPatient = personneRDV.First().prenom;
string heureRDV = rdv.Date.ToString().Substring(10, 9);
TextRDV.Text = " RENDEZ VOUS DANS " + Globals.TempRappelRDV.ToString() + " min \n Patient: \n Nom: " + NomPatient + "\n Prenom: " + PrenomPatient + "\n Heure: " + heureRDV + "\n\t\t" + DateTime.Now.ToString();
ListeNotif.Items.Add(TextRDV);
System.Windows.Forms.NotifyIcon notif = new System.Windows.Forms.NotifyIcon();
notif.Visible = true;
notif.Icon = new System.Drawing.Icon(#"../../ressources/Icones/icones ico/logo_white.ico");
notif.ShowBalloonTip(5000, "Medicare", "Vous un rendez vous important dans " + Globals.TempRappelRDV.ToString() + " minutes ", System.Windows.Forms.ToolTipIcon.Info);
cpt++;
}
}
}
}
}
}
}
}
I think Thread class is not the recommended way of executing code in the background even if you create just one thread and keep using it.You can use the TaskFactory to create one Long-Running Task. After that, you can add a while(true) loop to keep running the logic notification here.
//This should be stored in the resources, or some kind of configuration class
public string con = $#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename={System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)}\MCDatabase.mdf;Integrated Security=True";
In the constructor you can create the task.
public MenuPrincipal()
{
InitializeComponent();
UserControl usc = new Menu(ListRDV);
SelectionGrid.Children.Add(usc);
usc.VerticalAlignment = VerticalAlignment.Stretch;
usc.HorizontalAlignment = HorizontalAlignment.Stretch;
WindowStartupLocation = WindowStartupLocation.CenterScreen;
Globals.TempcalculNotif = 60;
Globals.TempRappelRDV = 15;
Task.Factory.StartNew(notification, TaskCreationOptions.LongRunning);
}
As you can see, I told the Scheduler that, this task is a long-running one.
private async void notification()
{
MCDataClassDataContext dataClass = new MCDataClassDataContext(con);
while (true)
{
await Task.Delay(TimeSpan.FromSeconds(3));
IQueryable<RendezVous> NotifRdv = (from rendezVous in dataClass.RendezVous
orderby rendezVous.Date
select rendezVous);
int cpt = 0;
if (NotifRdv.Count() != 0)
{
foreach (RendezVous rdv in NotifRdv)
{
string dateRdv, dateAJRD;
dateRdv = rdv.Date.ToString().Substring(0, 10);
dateAJRD = DateTime.Today.ToString().Substring(0, 10);
if (string.Compare(dateRdv, dateAJRD) == 0)
{
DateTime t1 = (DateTime)rdv.Date;
DateTime t2 = DateTime.Now;
TimeSpan t = t2 - t1;
if (t.TotalMinutes < Globals.TempRappelRDV)
{
if (rdv.IdPatient != 0)
{
if (rdv.Important == true)
{
TextBlock TextRDV = new TextBlock();
IQueryable<Patient> patientRDV = (from patient in dataClass.Patient
where rdv.IdPatient == patient.Id
select patient);
IQueryable<Personne> personneRDV = (from personne in dataClass.Personne
where patientRDV.First().IdPersonne == personne.Id
select personne);
string NomPatient = personneRDV.First().nom;
string PrenomPatient = personneRDV.First().prenom;
string heureRDV = rdv.Date.ToString().Substring(10, 9);
TextRDV.Text = " RENDEZ VOUS DANS " + Globals.TempRappelRDV.ToString() + " min \n Patient: \n Nom: " + NomPatient + "\n Prenom: " + PrenomPatient + "\n Heure: " + heureRDV + "\n\t\t" + DateTime.Now.ToString();
ListeNotif.Items.Add(TextRDV);
System.Windows.Forms.NotifyIcon notif = new System.Windows.Forms.NotifyIcon();
notif.Visible = true;
notif.Icon = new System.Drawing.Icon(#"../../ressources/Icones/icones ico/logo_white.ico");
notif.ShowBalloonTip(5000, "Medicare", "Vous un rendez vous important dans " + Globals.TempRappelRDV.ToString() + " minutes ", System.Windows.Forms.ToolTipIcon.Info);
cpt++;
}
}
}
}
}
}
}
Whenever you want to communicate with object owned by the UI thread you can use the Dispatcher for this. Although, I really don't know why are you writing your code in this manner. But I just provided an answer for your specific question.
I would suggest that your notification function should enter a while(true) in order to keep executing the logic and keep checking
private void notification()
{
//do your logic here
Thread.Sleep(1000); //this time is every second (1000 ms)
}
I have the following code:
static void Main(string[] args)
{
DateTime currentDay = DateTime.Now;
List<Task> taskList = new List<Task>();
List<string> markets = new List<string>() { "amex", "nasdaq", "nyse", "global" };
Parallel.ForEach(markets, market =>
{
Downloads.startInitialMarketSymbolsDownload(market);
}
);
Console.WriteLine("All downloads finished!");
}
public static void startInitialMarketSymbolsDownload(string market)
{
try
{
object valueTypeLock = new object();
List<string> symbolList = new List<string>() { "GOOG", "YHOO", "AAP" }
var historicalGroups = symbolList.AsParallel().Select((x, i) => new { x, i })
.GroupBy(x => x.i / 100)
.Select(g => g.Select(x => x.x).ToArray());
historicalGroups.AsParallel().ForAll(g => {
lock (valueTypeLock) {
getHistoricalStockData(g, market);
}
});
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
}
public static void getHistoricalStockData(string[] symbols, string market)
{
// download data for list of symbols and then upload to db tables
Uri uri;
string url, line;
decimal open = 0, high = 0, low = 0, close = 0, adjClose = 0;
DateTime date;
Int64 volume = 0;
string[] lineArray;
List<string> symbolError = new List<string>();
Dictionary<string, string> badNameError = new Dictionary<string, string>();
System.Net.ServicePointManager.DefaultConnectionLimit = 1000;
Parallel.ForEach(symbols, symbol =>
{
url = "http://ichart.finance.yahoo.com/table.csv?s=" + symbol + "&a=00&b=1&c=1900&d=" + (DateTime.Now.Month - 1) + "&e=" + DateTime.Now.Day + "&f=" + DateTime.Now.Year + "&g=d&ignore=.csv";
uri = new Uri(url);
using (ooplesfinanceEntities entity = new ooplesfinanceEntities())
using (WebClient client = new WebClient())
using (Stream stream = client.OpenRead(uri))
using (StreamReader reader = new StreamReader(stream))
{
entity.Database.Connection.Open();
while (reader.EndOfStream == false)
{
line = reader.ReadLine();
lineArray = line.Split(',');
// if it isn't the very first line
if (lineArray[0] != "Date")
{
switch (market)
{
case "amex":
DailyAmexData amexData = new DailyAmexData();
var amexQuery = from r in entity.DailyAmexDatas.AsParallel().AsEnumerable()
where r.Date == date
select new StockData { Close = r.AdjustedClose };
List<StockData> amexResult = amexQuery.AsParallel().ToList();
if (amexResult.AsParallel().Count() > 0) // **never hits this breakpoint line**
{
// add the row to the table if it isn't there
// now checks for stock splits and updates if necessary
if (amexResult.AsParallel().FirstOrDefault().Close != adjClose)
{
// this means there is a stock split so it needs to have the other adjusted close prices updated
amexResult.AsParallel().FirstOrDefault().Close = adjClose;
}
else
{
continue;
}
}
else
{
// set the data then add it
amexData.Symbol = symbol;
entity.DailyAmexDatas.Add(amexData);
}
break;
default:
break;
}
}
}
// now save everything
entity.SaveChanges();
Console.WriteLine(symbol + " added to the " + market + " database!");
}
}
);
}
Everything starts fine and I get no exceptions but I'm getting no results and the code gets stuck one the line that I marked and the memory keeps shooting up. I figured the problem was with the above code because maybe I was doing something wrong. I just don't know where to start as this is my first time dealing with plinq/parallel processing and the tutorials don't show anything this complex.
Edit: ok I know the query is incorrect. When I remove the TimeCreated part I get results back. What is the proper way to pull all events for that given day?
startTime = DateTime.Now.Date
string query = "*[System/Level=1 or System/Level=2] and TimeCreated[#SystemTime >= '" + startTime + "']";
using (EventLogSession session = new EventLogSession(serverName))
{
EventLogQuery eventQuery = new EventLogQuery(logName, PathType.LogName, query);
eventQuery.Session = session;
using (EventLogReader reader = new EventLogReader(eventQuery))
{
for (EventRecord eventDetail = reader.ReadEvent(); eventDetail != null; eventDetail = reader.ReadEvent())
{
entries.Add(eventDetail);
}
}
}
I have tired the following as well
"*[System/Level=1 or System/Level=2] and *[System/TimeCreated[#SystemTime >= '" + startTime + "']]";
"*[System[(Level=1) or System[(Level=2)] and TimeCreated[#SystemTime >= '" + startTime.ToUniversalTime().ToString("o") + "']]";
Here I made a helper to retrieve log from the event viewer, you can parametrized it quite easily
public static void WriteEventViewerHistoryByTypes(IList<EventViewerCriticalityLevel> levelTypes, string logType, string filePath, IList<string> sources, DateTime? startDate = new System.Nullable<DateTime>(), DateTime? endDate = new System.Nullable<DateTime>())
{
if (levelTypes == null || levelTypes.Count == 0)
levelTypes = new List<EventViewerCriticalityLevel> { EventViewerCriticalityLevel.Comment, EventViewerCriticalityLevel.Error, EventViewerCriticalityLevel.Fatal, EventViewerCriticalityLevel.Info, EventViewerCriticalityLevel.Warning };
StringBuilder sb = new StringBuilder();
sb.Append("<QueryList>");
sb.AppendFormat("<Query Id=\"0\" Path=\"{0}\">", logType);
sb.AppendFormat(" <Select Path=\"{0}\">", logType);
sb.AppendFormat(" *[System[(");
sb.AppendFormat("({0})", string.Join(" or ", levelTypes.Select(lev =>
{
if (lev == EventViewerCriticalityLevel.Info)
return string.Format("Level={0} or Level=0", (int)lev);
else
return string.Format("Level={0}", (int)lev);
})));
if (sources != null && sources.Count > 0)
{
sb.AppendFormat(" or ");
sb.AppendFormat("(Provider[{0}])", string.Join(" or ", sources.Select(el => "#Name='" + el + "'")));
}
sb.AppendFormat(")");
if (startDate.HasValue)
{
sb.AppendFormat(" and TimeCreated[#SystemTime >= '{0}']", startDate.Value.ToString("o"));
}
if (endDate.HasValue)
{
sb.AppendFormat(" and TimeCreated[#SystemTime <= '{0}']", endDate.Value.ToString("o"));
}
sb.AppendFormat("]]");
sb.AppendFormat(" </Select>");
sb.AppendFormat("</Query>");
sb.Append("</QueryList>");
try
{
EventLogSession sess = new EventLogSession();
sess.ExportLogAndMessages(logType, PathType.LogName, sb.ToString(), filePath, true, CultureInfo.CurrentCulture);
}
catch (Exception ex)
{
throw ex;
}
}
And here the enum
public enum EventViewerCriticalityLevel
{
Fatal = 1,
Error = 2,
Warning = 3,
Info = 4,
Comment = 5
}
It will generate evtx files that you can read with the event viewer console.
Hope it helps !
I have a program that upon loading the user control, adds graphics to a map layer (You shouldn't have to know much about map stuff to help, I believe the problem is with my loop logic.)
Here is my code:
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
con = new System.Data.SqlClient.SqlConnection();
con.ConnectionString = "Data Source=USSW7DEVWS16\\DEVELOPER;Initial Catalog=acrGIS;Integrated Security=True";
con.Open();
using (SqlCommand command = new SqlCommand("SELECT * FROM arcObjects", con))
{
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
int ID = reader.GetInt32(0);
Object = reader.GetString(1);
OComment = reader.GetString(2);
OStreet = reader.GetString(3);
OCity = reader.GetString(4);
OState = reader.GetString(5);
OZip = reader.GetString(6);
OSpec = reader.GetString(7);
arcObjects.Add(new arcObject() { Object_Num = Object, Comments = OComment, Street = OStreet, City = OCity, State = OState, Zip = OZip, Spec = OSpec });
}
con.Close();
foreach (arcObject objects in arcObjects)
{
Locator InitialLocatorTask = new Locator("http://tasks.arcgisonline.com/ArcGIS/rest/services/Locators/TA_Streets_US_10/GeocodeServer");
InitialLocatorTask.AddressToLocationsCompleted += InitialLocatorTask_AddressToLocatonCompleted;
InitialLocatorTask.Failed += InitialLocatorTask_Failed;
AddressToLocationsParameters addressParams = new AddressToLocationsParameters();
Dictionary<string, string> address = addressParams.Address;
address.Add("Street", objects.Street);
address.Add("City", objects.City);
address.Add("State", objects.State);
address.Add("Zip", objects.Zip);
InitialLocatorTask.AddressToLocationsAsync(addressParams);
}
}
}
private void InitialLocatorTask_AddressToLocatonCompleted(object sender, ESRI.ArcGIS.Client.Tasks.AddressToLocationsEventArgs args)
{
con = new System.Data.SqlClient.SqlConnection();
con.ConnectionString = "Data Source=USSW7DEVWS16\\DEVELOPER;Initial Catalog=acrGIS;Integrated Security=True";
con.Open();
using (SqlCommand command = new SqlCommand("SELECT * FROM arcObjects", con))
{
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
int ID = reader.GetInt32(0);
Object = reader.GetString(1);
OComment = reader.GetString(2);
OStreet = reader.GetString(3);
OCity = reader.GetString(4);
OState = reader.GetString(5);
OZip = reader.GetString(6);
OSpec = reader.GetString(7);
CandidateListBox.Items.Clear();
List<AddressCandidate> returnedCandidates = args.Results;
foreach (AddressCandidate candidate in returnedCandidates)
{
if (candidate.Score >= 80)
{
CandidateListBox.Items.Add(candidate.Address);
if (OSpec == "Meter")
{
Graphic graphic = new Graphic()
{
Symbol = AddressLayout.Resources["WaterMeterRenderer"] as ESRI.ArcGIS.Client.Symbols.Symbol,
Geometry = candidate.Location
};
string address2 = OCity + ", " + OState + " " + OZip;
graphic.Attributes.Add("MeterNum", Object);
graphic.Attributes.Add("Comment", OComment);
graphic.Attributes.Add("Address1", OStreet);
graphic.Attributes.Add("Address2", address2);
if (candidate.Location.SpatialReference == null)
{
candidate.Location.SpatialReference = new SpatialReference(4326);
}
// if (!candidate.Location.SpatialReference.Equals(MyMap.SpatialReference))
//{
// if (MyMap.SpatialReference.Equals(new SpatialReference(102100)) && candidate.Location.SpatialReference.Equals(new SpatialReference(4326)))
// graphic.Geometry = _mercator.FromGeographic(graphic.Geometry);
// else if (MyMap.SpatialReference.Equals(new SpatialReference(4326)) && candidate.Location.SpatialReference.Equals(new SpatialReference(102100)))
// graphic.Geometry = _mercator.ToGeographic(graphic.Geometry);
// else if (MyMap.SpatialReference != new SpatialReference(4326))
// {
GeometryService geometryService = new
GeometryService("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer");
geometryService.ProjectCompleted += (s, a) =>
{
graphic.Geometry = a.Results[0].Geometry;
};
geometryService.Failed += (s, a) =>
{
MessageBox.Show("Projection error: " + a.Error.Message);
};
//geometryService.ProjectAsync(new List<Graphic> { graphic }, MyMap.SpatialReference);
// }
//}
FeatureLayer graphicsLayer = MyMap.Layers["WaterMeterLayer"] as FeatureLayer;
graphicsLayer.Graphics.Add(graphic);
//return;
}
if (OSpec == "Lot")
{
Graphic graphic = new Graphic()
{
Symbol = AddressLayout.Resources["LotRenderer"] as ESRI.ArcGIS.Client.Symbols.Symbol,
Geometry = candidate.Location
};
string address2 = OCity + ", " + OState + " " + OZip;
graphic.Attributes.Add("MeterNum", Object);
graphic.Attributes.Add("Comment", OComment);
graphic.Attributes.Add("Address1", OStreet);
graphic.Attributes.Add("Address2", address2);
if (candidate.Location.SpatialReference == null)
{
candidate.Location.SpatialReference = new SpatialReference(4326);
}
//if (!candidate.Location.SpatialReference.Equals(MyMap.SpatialReference))
// {
// if (MyMap.SpatialReference.Equals(new SpatialReference(102100)) && candidate.Location.SpatialReference.Equals(new SpatialReference(4326)))
// graphic.Geometry = _mercator.FromGeographic(graphic.Geometry);
// else if (MyMap.SpatialReference.Equals(new SpatialReference(4326)) && candidate.Location.SpatialReference.Equals(new SpatialReference(102100)))
// graphic.Geometry = _mercator.ToGeographic(graphic.Geometry);
// else if (MyMap.SpatialReference != new SpatialReference(4326))
// {
GeometryService geometryService = new GeometryService("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer");
geometryService.ProjectCompleted += (s, a) =>
{
graphic.Geometry = a.Results[0].Geometry;
};
geometryService.Failed += (s, a) =>
{
MessageBox.Show("Projection error: " + a.Error.Message);
};
//geometryService.ProjectAsync(new List<Graphic> { graphic }, MyMap.SpatialReference);
// }
// }
FeatureLayer graphicsLayer = MyMap.Layers["LotLayer"] as FeatureLayer;
graphicsLayer.Graphics.Add(graphic);
// return;
}
}
}
}
}
con.Close();
}
public void InitialLocatorTask_Failed(object sender, TaskFailedEventArgs e)
{
MessageBox.Show("Locator service failed: " + e.Error);
}
I know what it happening, the foreach loop in the UserControl_Loaded is adding things to the dictionary and then the while loop in the InitailTaskToAddress_Completed runs over and over again (9 times to be exact). What the problem is, is though while all of the graphics are being placed in the correct place, the attributes of those graphics are all the same...
For some reason it is not getting them. If you want me to clear anything up, just let me know. Also, if you would like to see my XAML, I can also show you that. I am using C# and WPF, as well as arcGIS. Thank you for your help.