Present updating data

C

csharpula csharp

Hello,
I would like to know how can I present updating (on the fly) data in a
DataGrid type control. The control will get url as an input and need to
present the log changing content in a DataGrid style control.How to do
it in WinForms? Thank you!
 
M

Morten Wennevik [C# MVP]

Hi,

You can use a BackgroundWorker and manually read the stream, passing a log
entry to the GUI thread using invoke whenever you want.
 
M

Morten Wennevik [C# MVP]

If you paste the code below into a winform called Form1 and change <add web
address> to a valid web address, the code sample will ayncronously gradually
fill a DataGridView with rows as the web content is downloaded.

You need to change the download code and business object to suit your needs.

public partial class Form1 : Form
{
public Form4()
{
InitializeComponent();
}

BackgroundWorker worker = new BackgroundWorker();
protected override void OnLoad(EventArgs e)
{
DataGridView dataGridView1 = new DataGridView();
Controls.Add(dataGridView1);

dataGridView1.DataSource = list;

// Set up the BackgroundWorker
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.WorkerSupportsCancellation = true;

// Start the backgroundworker.
worker.RunWorkerAsync();
}

protected override void OnClosing(CancelEventArgs e)
{
// Notify the backgroundworker that the program is shutting down
// If you don't do this you will end up trying to update a
DataGridView that no longer exists.
if (worker.IsBusy)
worker.CancelAsync();
}


// This method will run asyncronously when worker is started
// Anything if you need to update the GUI thread from this method
you need to invoke.
void worker_DoWork(object sender, DoWorkEventArgs e)
{
// Create a request and response object to the uri
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(<add
web address>);

// If you need to go through a proxy, add necessary credentials
req.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials;
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();

// Get the stream returned from the web site
using (Stream s = resp.GetResponseStream())
{
byte[] data = new byte[8192];

// The memorystream is just holding the entire download.
You may not need it.
int i = 0;
int pos = 0;

// While there is data
while ((i = s.Read(data, 0, data.Length)) > 0)
{
// Check to see if the program has shut down
if (worker.CancellationPending)
return;

// Add a log entry
AddLogEntry("Title", Encoding.Default.GetString(data));

pos += i;

// Simulate lengty procedure by sleeping 1 second
Thread.Sleep(1000);
}
}
}

// This delegate will hold necessary data to be able to invoke
AddLogEntry.
// The parameter types must mach the called method.
delegate void StringStringDelegate(string title, string text);

// This method will add a LogEntry object to 'list'
public void AddLogEntry(string title, string text)
{
// Since we are receiving calls from a non GUI thread pass the
call to the GUI thread using a delegate
if(InvokeRequired)
{
this.Invoke(new StringStringDelegate(AddLogEntry), new
object[]{title, text});
return;
}
list.Add(new LogEntry(title, text));
}

// A bindinglist will notify the DataGridView when it has new items
BindingList<LogEntry> list = new BindingList<LogEntry>();

// The business object to be listed in the DataGridView
class LogEntry
{
private string _title;

public string Title
{
get { return _title; }
set { _title = value; }
}

private string _text;

public string Text
{
get { return _text; }
set { _text = value; }
}

public LogEntry(string title, string text)
{
this.Title = title;
this.Text = text;
}
}
}
 
C

csharpula csharp

Thanks but I don't understand how can I know that there is an update in
the log which is located in the url?
 
M

Morten Wennevik [C# MVP]

If you need to read the url each time you want to update the log status
instead of just once, for a huge log (which my example assumed), rewrite the
download part to reside inside an eternal loop. You need to poll the url
every so often to find out if there are any changes to the log. Remember to
check for CancellationPending inside this loop or the BackgroundWorker won't
stop.
 
C

csharpula csharp

Hello,
I tried to do this:

while (true)
{
using (Stream s = resp.GetResponseStream())
{
byte[] data = new byte[8192];

int i = 0;
int pos = 0;

while ((i = s.Read(data, 0, data.Length)) > 0)
{
if (worker.CancellationPending)
return;

AddLogEntry("Title",
Encoding.Default.GetString(data), "blabla");

pos += i;

Thread.Sleep(1000);
}
}
}

But I get the following error:

The request was aborted: The connection was closed unexpectedly.

And isn't ther more elegant way than endless loop?
Thank you very much!
 
M

Morten Wennevik [C# MVP]

You need to encapsulate everything including HttpWebRequest.

If the size of the log isn't an issue, you can easily use a WebClient
instead of request/response.

WebClient client = new WebClient();
// Set proxy credentials if needed
client.Proxy.Credentials =
CredentialCache.DefaultNetworkCredentials;
while (true)
{
byte[] data = client.DownloadData(<add web address>);
if (worker.CancellationPending)
return;

AddLogEntry("Title", Encoding.Default.GetString(data));
Thread.Sleep(1000); // For testing purposes
}

You won't have the opportunity to notify the GUI during download, but
usually text is downloaded fairly fast anyway.

However, I'm wondering if maybe you just need a way to download the log once
in the background, in which case just remove the while loop. If you need
regular updates you could also have a timer in the main GUI thread and let
the timer event start the worker.
 
C

csharpula csharp

Hello again,
Well I need some kind of FileSystemWatcher class but which will do the
pooling to the url ,how to do that? The log file I got is being updated
all the time during some process on remote comp and i need that my c#
gui will present the changes all the time. How to do such a Watcher in
the code you posted? Thank u!
 
M

Morten Wennevik [C# MVP]

Ok, correct me if I am wrong.

You have a GUI application on one computer that should display any changes
in a log file on another computer, preferrably as soon as they occur in the
log file?

My code should cover the first part, downloading the log every so often.

As for 'pooling to the url'. I'm not sure what you mean by this. Do you
seek a solution where the remote computer actively updates any client
listening to it? Or maybe have the remote computer 'post' the log file to a
public web site where you can get it to your local computer?

The simplest way would be to have a web service running on the remote
computer with read access to the log file. Whenever you call this web
service (like from a background worker started by a timer) the web service
will then go and get the latest log information.
 
C

csharpula csharp

Hello,
About the gui part - I have a c# gui which communicates via web service
with other computer. There is some process on other computer which
updates the log that I need to present on my computer (with any change).
The question is how will I know that the log is updated and will present
only the "delta" change of the log attached to the previous log data I
presented already?
Thanks a lot!
 
M

Morten Wennevik [C# MVP]

The web service is not able notify you of any change. The GUI client needs
to regularly call the web service and read the log and compare it with a
local copy.
 
C

csharpula csharp

Thank u and what is the best way to compare ? Is there a way to read by
lines from a stream (and this will help me to compare) or I will get all
the data in one string?
 
B

Ben Voigt [C++ MVP]

Morten Wennevik said:
The web service is not able notify you of any change. The GUI client
needs
to regularly call the web service and read the log and compare it with a
local copy.

The web service should be rewritten to return only new entries, this avoid
unnecessarily copying the old section of the log across the network multiple
times.

If the log is append-only, this is as simple as including the file length in
the data from the web service, and passing that to the web service on the
next invocation so it can send the data starting at that position.
--
Happy Coding!
Morten Wennevik [C# MVP]


csharpula csharp said:
Hello,
About the gui part - I have a c# gui which communicates via web service
with other computer. There is some process on other computer which
updates the log that I need to present on my computer (with any change).
The question is how will I know that the log is updated and will present
only the "delta" change of the log attached to the previous log data I
presented already?
Thanks a lot!
 
C

csharpula csharp

Is it possible to read oin each iteration from the last readed bytes
till the end? If so ,how should I do it? I want to find a solution which
won't involve making changes in web srvice. Thank you!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top