Click here to Skip to main content
15,899,474 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
C#
private void btnUpload_Click(object sender, EventArgs e)
        {
            try
            {
                string bucketName = string.Empty, fileName = string.Empty;//, 
                accessKey = string.Empty, SecretKey = string.Empty;
                this.Cursor = Cursors.WaitCursor;
                bucketName = "ben-s3lambdaevent"; //"ben-hrms";
                fileName = string.Format("{0}", this.SoftCopyFileName);

                //AmazonS3 s3Obj = new AmazonS3();
                string msg = UploadFile(bucketName, openFileDialog1.FileName, fileName);

                if (msg.ToUpper() == SUCCESS_MSG)
                {
                    btnBrowse.Enabled = false;
                }
                DataTable table = new DataTable();
                
                Amazon.RegionEndpoint region = Amazon.RegionEndpoint.APSouth1;
                table = GetS3SelectDetails(accessKey, SecretKey, bucketName, fileName, region);
                dgvGrid.DataSource = table;
                this.Cursor = Cursors.Default;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, TECHNO_MSG);
                //if (access == null) access = new BusinessConnector();
                //access.DBConnector.ErrorLogInsert(ex.Message, "frmServiceInvoice.cs.btnBrowse_Click()");
            }
        }

        public DataTable GetS3SelectDetails(string accessKey, string SecretKey, string bucketName, string fileName, Amazon.RegionEndpoint region)
        {
            DataTable dt = (DataTable)GetAmazonS3Select(accessKey, SecretKey, bucketName, fileName, region).Result;

            return dt;
        }

        public async Task<datatable> GetAmazonS3Select(string accessKey, string SecretKey, string bucketName, string fileName, Amazon.RegionEndpoint region)
        {
            DataTable table = new DataTable();
            using (var eventStream = await GetSelectObjectContentEventStream(accessKey, SecretKey, bucketName, fileName, region))
            {
                var recordResults = eventStream
                .Where(ev => ev is RecordsEvent)
                .Cast<recordsevent>()
                .Select(records =>
                {
                    using (var reader = new StreamReader(records.Payload, Encoding.UTF8))
                    {
                        return reader.ReadToEnd();
                    }
                }).ToArray();

                string[] fileData = recordResults[0].ToString().Split('\n');

                for (int i = 0; i < fileData.Length; i++)
                {
                    string[] rowData = fileData[i].ToString().Split(';');

                    if (i == 0)
                    {
                        for (int j = 0; j < rowData.Length; j++)
                        {
                            table.Columns.Add(rowData[j].ToString(), typeof(string));
                        }
                    }
                    else
                    {
                        DataRow row = table.NewRow();
                        for (int j = 0; j < rowData.Length; j++)
                        {
                            row[j] = rowData[j].ToString();
                        }
                        table.Rows.Add(row);
                    }
                }
            }
            return table;
        }

        public async Task<iselectobjectcontenteventstream> GetSelectObjectContentEventStream(string accessKey, string SecretKey, string bucketName, string fileName, Amazon.RegionEndpoint region)
        {
            SelectObjectContentResponse response1 = null;
            try
            {
                IAmazonS3 client1 = new AmazonS3Client(accessKey, SecretKey, region);

                SelectObjectContentRequest request = new SelectObjectContentRequest();
                request.Bucket = bucketName;
                request.Key = fileName;
                request.ExpressionType = Amazon.S3.ExpressionType.SQL;
                request.Expression = "select * from S3Object";

                request.InputSerialization = new InputSerialization()
                {
                    CSV = new CSVInput()
                    {
                        FileHeaderInfo = FileHeaderInfo.Use
                        //FieldDelimiter = ";",
                    }
                };

                request.OutputSerialization = new OutputSerialization()
                {
                    CSV = new CSVOutput()
                    {
                        //QuoteFields = QuoteFields.Always
                        FieldDelimiter = ";"
                    }
                };
   ------------  response1 = await client1.SelectObjectContentAsync(request);
            }
            catch (Exception ex)
            {

            }
            return response1.Payload;
        }


What I have tried:

after uploading the data iam unable to read last (response1 = await) cursor is running but date is not getting please help me
Posted
Updated 14-May-19 9:10am
v2
Comments
[no name] 14-May-19 9:10am    
If you're asking "is my code maintainable"? No.

1 solution

Sorry this is going to be quite technical. The async/await appears to be very simple. It isn't.

TL;DR below.

For a beginner, I recommend ensuring your entire application is async, or nothing is async. As soon you start mixing it you will get deadlocks unless you have very precise knowledge of how the async code is executed. In this context, mixing it specifically means calling Wait or Result on a Task object returned by an async method.

One of the lessons mostly learned the hard way is that await will not start a new thread. The method you call async might choose to use a new thread but is never guarantied to do so. When it choose to do so, it will deliver the result back on the thread it was called for unless you specifically tell it not to (and if you do, you need to ensure the code after await can run on a new thread - which it can't in your case as it updates the UI.

For your concrete example you call await from the main UI thread. This means all code executes on the main UI thread - which is typically a good thing, unless there is some heavy computations (in your case there isn't, so don't try to move it off to another tread - it will just make it slower and harder to maintain... and it would still lock up).

From
btnUpload_Click
you call
GetS3SelectDetails
This call is not using await. This means once the UI thread returns from GetS3SelectDetails it must have the table retrieved from S3. If the await keyword had been used, it would basically tell the UI thread to wait with the remaining part of the code until the table is available.

From GetS3SelectDetails you call
GetAmazonS3Select
This makes GetAmazonS3Select start executing until it reach
response1 = await client1.SelectObjectContentAsync(request);
As the result of this call is not available right away (it needs to make the network call), the method returns a Task where it will set the result once it is available. But the important thing is it returns to GetS3SelectDetails right away where you then call the Result property on the returned task.

When you call Result, you have what is known as a blocking call. This means the main UI thread is now sitting waiting for someone else to set the result. It can't do anything else. It can't handle other button clicks, let you move your window etc. It will do nothing but wait for that result.

The next that happens is the result comes back from the network call. This is typically handled by another thread, so no problem... until it want to set the result on the Task. As I wrote earlier, this will per default (and do not change the default, you do not understand enough to do that yet) want to run the code on the same thread it was called on.

So you now have:
1) The main UI thread sitting in the .Result property waiting for a result
2) Another threat waiting for the UI thread to be available so it can set the result.

So both threads will stop processing anything and just sit there.

How to fix this:

First change the methods btnUpload_Click and GetS3SelectDetails so they are async and return tasks.

Something like:
private async Task btnUpload_Click(object sender, EventArgs e)...
public Task<DataTable> GetS3SelectDetails(string accessKey, string SecretKey, string bucketName, string fileName, Amazon.RegionEndpoint region)...


Now change GetS3SelectDetails so it calls GetAmazonS3Select async (so it won't block waiting for the result):
DataTable dt = await (DataTable)GetAmazonS3Select(accessKey, SecretKey, bucketName, fileName, region);


Finally you also need to make sure the call to GetS3SelectDetails is awaiting as well:
table = await GetS3SelectDetails(accessKey, SecretKey, bucketName, fileName, region);


As a result, the main UI thread will execute the code until the network call right away, then it will return to process messages for the UI (so allow other button clicks, moving the window etc). Once the table is returned, the main UI thread will pick it up and run the rest of your code.

TL;DR

If this is too complicated for you to fully understand yet (you will get there, don't worry), just make the suggested changes and take this key lesson away from this: If you call .Result or .Wait, your UI will hang. So any method calling an async method must be async itself.

Oh yes.. another thing... Don't do catch with an empty code block unless you really hate the following two persons (which might be the same guy, might even be you):
1) The user of your application
2) The developer who has to figure out why it is not working.

If you are certain those two are the most disgusting persons to ever live and they deserve all evil that can be thrown in their general direction, then by all means use catch {}.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900