【问题标题】:The GUI is not moving properlyGUI 没有正确移动
【发布时间】:2021-03-12 15:35:32
【问题描述】:

我正在做一个小部件,使用 Binance API here 显示比特币价格

我没有使用 Json 格式,因为我只需要解析一个字符串,尽管我知道你们中的许多人会说使用 json。无论如何,我想让软件尽可能简单,但是有一个小问题。 我正在使用 webclient 下载源代码并使用计时器对其进行更新。 我认为每次创建新的网络客户端时我都犯了一个错误,因为当我想移动表单时,即使它没有冻结也不能正确移动。 我使用的代码是:

Private Sub webclientbtc()
       Dim wc As New Net.WebClient
       Dim WBTC As IO.Stream = Nothing
       wc.Encoding = Encoding.UTF8
       WBTC = wc.OpenRead("https://api.binance.com/api/v1/ticker/24hr?symbol=BTCEUR")
       Dim btc As String
       Using rd As New IO.StreamReader(WBTC)
           btc = rd.ReadToEnd
       End Using
       '---------BTC PRICE---------'
       Dim textBefore As String = """lastPrice"":"""
           Dim textAfter As String = ""","
           Dim startPosition As Integer = btc.IndexOf(textBefore)
           startPosition += textBefore.Length
           Dim endPosition As Integer = btc.IndexOf(textAfter, startPosition)
       Dim textFound As String = btc.Substring(startPosition, endPosition - startPosition)
       Dim dNumber As Double = Val(textFound.ToString)
       Label1.Text = dNumber.ToString("n2")
       '-------------------------------------'
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
       webclientbtc()
   End Sub

计时器间隔为 1000 毫秒,这对我保持更新非常有用。 关于如何避免在每次更新时创建新的 webclient 有什么想法吗? 谢谢

【问题讨论】:

  • WebClient 确实有一个 .Dispose 方法,因此应该在创建另一个之前处理它。如果您使用表单级别的 New WebClient,请在应用程序末尾找到一个放置位置。
  • 我正在考虑在计时器滴答期间处理它,这是个好主意吗?
  • 您可以在webclientbtc 方法中使用Using 块。 End Using 处理。 Tick 事件不包含对 WebClient 的引用,因此无法在此处处理。

标签: vb.net webclient


【解决方案1】:

简化并使用 TAP:

Private wc as New WebClient()

Private Async Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    Dim s = Await wc.DownloadStringTaskAsync("https://api.binance.com/api/v1/ticker/24hr?symbol=BTCEUR")
    Dim d = JsonConvert.DeserializeObject(Of Dictionary(Of String, String))(s)
    Label1.Text = d("lastPrice")
End Sub

你需要引用newtonsoft json包并导入它,以及导入system.collections.generic

【讨论】:

  • 嗨,Caius,谢谢,但正如我所说,我想让它尽可能简单,我现在不想使用 Json。谢谢
  • 这并不难:在最新的 VS2019 中粘贴代码,指向 JsonConvert 下的红色摆动线,单击灯泡并选择菜单底部的“Install Package Newtonsoft..”。结束。在较旧的 VS 中,您右键单击项目,选择“管理 Nuget 包”,单击浏览,键入“Newtonsoft”,单击下载量近十亿的条目,单击安装,然后粘贴代码。如果你得到任何其他红色的摆动线,你指向它们并让 VB 为你做导入。使用复杂的切弦方法更难(而且更糟,需要更长的时间)!
  • 嗨,Caius 你是完全正确的,我知道。 Json 是最快的方法,也是唯一的“逻辑”解决方案。无论如何,因为这对我自己来说是一个简单的小部件,所以我做的很简单,因为我想解析高价和低价,更改和更改百分比数据。出于这个原因,我的字符串方法是有效的,我对此很有信心。只是认为问题是我没有处理网络客户端。
  • 我做的很简单 - 不。关于你的字符串切割方式,没有什么比说“嘿,世界排名第一的 JSON 解析器,为我解析这个,谢谢”这么简单。 还因为我想解析高价和低价,更改和更改百分比数据 - 所以你承认你会想要解析更多的数据.. 什么,更多的字符串切割?当我已经向您展示了路径时,您可以再写 1 行代码说 d("priceChange")d("highPrice") 并获得您想要的数据?好的..如果您对此没有采取任何其他措施,至少制作一个网络客户端并使用 TAP
  • 也许还值得一提的是,您避免使用 JSON 解析,而是有效地编写自己的解析,但您不会通过编写自己的 HTTP 客户端/whip 来手动下载这些数据出一个 TCP 套接字,连接它,手动推送字节,将响应读入缓冲区,将其从字节数组转换为字符串。所以你很高兴使用一个高级抽象帮助器类来完成下载位,但坚决反对使用另一个高级 JSON 解析库来理解您下载的内容 - 这实际上没有任何逻辑意义
【解决方案2】:

如果answer by Caius Jard 太好了,您可以通过使用正则表达式来避免使用 JSON 反序列化器:

Imports System.Net
Imports System.Text.RegularExpressions

Public Class Form1

    Dim tim As New Timer()

    Private Async Sub UpdateBtc(sender As Object, e As EventArgs)
        ' temporarily disable the timer in case the web request takes a long time
        tim.Enabled = False

        ' using New Uri() makes sure it is a proper URI: 
        Dim url = New Uri("https://api.binance.com/api/v1/ticker/24hr?symbol=BTCEUR")
        Dim rawJson As String

        Using wb As New WebClient()
            rawJson = Await wb.DownloadStringTaskAsync(url)
        End Using

        Dim re = New Regex("""lastPrice"":\s*""([0-9.-]+)""")
        Dim lastPrice = re.Match(rawJson)?.Groups(1)?.Value

        Dim p As Decimal
        lblLastPrice.Text = If(Decimal.TryParse(lastPrice, p), p.ToString("N2"), "Fetch error.")

        tim.Enabled = True

    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        UpdateBtc(Nothing, EventArgs.Empty)
        tim.Interval = 3000
        AddHandler tim.Tick, AddressOf UpdateBtc
        tim.Start()

    End Sub

    Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
        If tim IsNot Nothing Then
            tim.Stop()
            RemoveHandler tim.Tick, AddressOf UpdateBtc
            tim.Dispose()
        End If

    End Sub

End Class
  • 无需重复使用 WebClient,创建它并不占用时间。
  • 我更喜欢自己实例化计时器:没有必要这样做。
  • 最好为控件使用描述性名称:“Label1”不会告诉您任何信息。

【讨论】:

  • 您好安德鲁,感谢您的回答。但正如我所说,我不会使用 Json,因为这对我来说是一个简单的工具,而 Json 对我来说仍然不是很清楚。
  • @23rfwefaf 这个答案不使用 JSON。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多