嗨朋友们可以帮助我。如何从AWS S3存储桶读取xlsx / csv文件到C#窗体格式视图。我的代码下面是 [英] Hi friends can any one help me. How to read the xlsx/csv file from AWS S3 bucket to C# windows forms gridview. Below my code is

查看:79
本文介绍了嗨朋友们可以帮助我。如何从AWS S3存储桶读取xlsx / csv文件到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;
        }





我的尝试:



上传了最后无法读取的数据(response1 = await)光标正在运行但是日期没有得到请帮帮我



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

推荐答案

对不起这个将是非常技术性的。 async / await看起来非常简单。它不是。



TL; DR低于。



对于初学者,我建议你确保你的整个应用程序是异步的,或者没有异步。一旦你开始混合它,你就会遇到死锁,除非你非常精确地了解异步代码的执行方式。在这种情况下,混合它特别意味着在异步方法返回的Task对象上调用Wait或Result。



其中一个主要是学到很多困难的教训就是等待将开始一个新线程。您调用async 的方法可能选择使用新线程,但绝不保证这样做。当它选择这样做时,它会将结果传递回它所调用的线程,除非你明确告诉它不要(如果你这样做,你需要确保在等待可以在新线程上运行之后的代码 - 它在你的情况下不能更新UI。



对于你的具体例子,你从主UI线程调用await。这意味着所有代码都在主UI上执行线程 - 这通常是一件好事,除非有一些繁重的计算(在你的情况下没有,所以不要试图把它移到另一个步骤 - 它只会让它变得更慢,更难维护......并且它仍会锁定)。



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

你打电话给

GetS3SelectDetails

这个调用没有使用await。这意味着一旦UI线程从GetS3SelectDetails返回,它必须从S3检索表。如果使用了await关键字,它基本上会告诉UI线程等待剩下的直到选项卡的部分代码le可用。



来自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

这使得GetAmazonS3Select开始执行,直到达到

This makes GetAmazonS3Select start executing until it reach

response1 = await client1.SelectObjectContentAsync(request);

由于此调用的结果不可用(它需要进行网络调用),该方法返回一个Task,它将设置结果一旦可用。但重要的是它会立即返回到GetS3SelectDetails,然后在返回的任务上调用Result属性。



当您拨打结果时,您将拥有所谓的阻止呼叫。这意味着主UI线程现在正在等待其他人设置结果。它无能为力。它无法处理其他按钮点击,让你移动你的窗口等。它只会等待结果。



接下来发生的是结果来了从网络电话回来。这通常由另一个线程处理,所以没问题......直到它想要在Task上设置结果。正如我之前写的那样,这将默认(并且不要更改默认值,你还不能理解它)想要在调用它的同一个线程上运行代码。



所以你现在有:

1)坐在.Result属性中的主UI线程等待结果

2)另一个威胁在等待UI线程可用,因此可以设置结果。



因此两个线程都会停止处理任何东西而只是坐在那里。



如何解决这个问题:



首先更改方法btnUpload_Click和GetS3SelectDetails,使它们异步并返回任务。



类似于:

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)...





现在改变GetS3SelectDetails所以它调用GetAmazonS3Select async(因此它不会阻止等待结果):



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);





最后你还需要确保GetS3SelectDetails的调用正在等待:



Finally you also need to make sure the call to GetS3SelectDetails is awaiting as well:

table = await GetS3SelectDetails(accessKey, SecretKey, bucketName, fileName, region);





因此,主UI线程将执行代码,直到网络呼叫立即,然后它将返回处理UI的消息(因此允许其他按钮单击,移动窗口等)。一旦表格返回,主UI线程将提取并运行其余代码。



TL; DR



如果这对你来说太复杂而无法完全理解(你会到达那里,不要担心),只需进行建议的更改并从这个关键课程中取消:如果你调用.Result或.Wait,你的用户界面就会挂起。所以任何调用异步方法的方法都必须是异步的。



哦是的..另一件事......除非你真的,否则不要用空代码块捕获讨厌以下两个人(可能是同一个人,甚至可能是你):

1)你的申请的用户

2)开发人员必须要计算为什么它不起作用。



如果你确定这两个人是最恶心的人,他们应该得到所有邪恶,可以抛向他们的大方向,然后一定使用catch {}。



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 {}.


这篇关于嗨朋友们可以帮助我。如何从AWS S3存储桶读取xlsx / csv文件到C#窗体格式视图。我的代码下面是的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆