Home php c# sql c c++ javascript python java go android git linux asp.net django .net node.js ios xcode cocoa iphone mysql tomcat mongodb bash objective-c scala visual-studio apache elasticsearch jar eclipse jquery ruby-on-rails ruby rubygems android-studio spring lua sqlite emacs ubuntu perl docker swift amazon-web-services svn html ajax xml java-ee maven intellij-idea rvm macos unix css ipad postgresql css3 json windows-server vue.js typescript oracle hibernate internet-explorer github tensorflow laravel symfony redis html5 google-app-engine nginx firefox sqlalchemy lucene erlang flask vim solr webview facebook zend-framework virtualenv nosql ide twitter safari flutter bundle phonegap centos Register | Login | Edit Tags | New Questions | 繁体 | 简体


10 questions online user: 47

0
votes
answers
11 views
+10

爲什麼HttpClient PutAsync在成功更新後返回內部服務器錯誤

0

我有一個HttpPut API方法,用於編輯它傳遞併成功保存到數據庫中的對象。這工作正常,但是從我的MVC應用程序,我用來調用我的API Put方法的httpClient.PutAsync返回內部服務器錯誤,即使API Put方法沒有。爲什麼HttpClient PutAsync在成功更新後返回內部服務器錯誤

我不知道什麼錯誤,API方法工作正常,但不知何故MVC的HttpClient仍然得到一個內部服務器錯誤。

API put方法

[HttpPut] 
    public IActionResult Put([FromBody] School school) 
    { 
     try 
     { 
      var schoolExists = _schoolRepository.SchoolExists(school.Id); 

      if (!schoolExists) return NotFound(); 

      if (!ModelState.IsValid) return BadRequest(); 

      var schoolData = Mapper.Map<School, Data.School>(school); 

      var updatedClass = _schoolRepository.UpdateSchool(schoolData); 

      if (!updatedClass) return Json(GetHttpResponseMessage(HttpStatusCode.InternalServerError)); 

      var route = CreatedAtRoute("GetSchool", school); 

      return route; 
     } 
     catch (Exception e) 
     { 
      return LogException(e); 
     } 
    } 

上述方法,工作正常,我的改變被保存到數據庫中,CreatedAtRouteResult對象從API方法返回。上述

MVC的HttpClient

public async Task<T> PutObject(string path, T content, string accessToken) 
    { 
     using (var httpClient = new HttpClient()) 
     { 
      try 
      { 
       SetBaseUri(httpClient, accessToken); 

       var serialisezContent = CreateHttpContent(content); 

       var httpResponse = await httpClient.PutAsync(path, serialisezContent); 

       if (httpResponse.StatusCode == HttpStatusCode.InternalServerError) throw new Exception("Problem accessing the api"); 

       return JsonConvert.DeserializeObject<T>(GetResult(httpResponse)); 
      } 
      catch (Exception ex) 
      { 
       throw ex; 
      } 
     } 

    } 

的方法,其中是問題是,這條線var httpResponse = await httpClient.PutAsync(path, serialisezContent);仍返回內部服務器錯誤。我的POST有相同的實現,並且工作得很好。

SETBASEURI()

private void SetBaseUri(HttpClient httpClient, string accessToken) 
    { 
     httpClient.BaseAddress = new Uri(BaseUri); 
     httpClient.DefaultRequestHeaders.Authorization = 
      _authenticationHeaderValueCreator.CreateAuthenticationHeaderValue("bearer", accessToken); 
    } 

CreateHttpContent()

public ByteArrayContent CreateHttpContent<TParam>(TParam httpObject) 
    { 
     var content = JsonConvert.SerializeObject(httpObject); 
     var buffer = System.Text.Encoding.UTF8.GetBytes(content); 
     var byteContent = new ByteArrayContent(buffer); 

     byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); 

     return byteContent; 
    } 
沙发
0
0

我敢打賭,你的API Put方法確實有消息No route matches the supplied values返回HTTP 500錯誤。你可以在Fiddler中檢查它。

而問題是具有以下線:

var route = CreatedAtRoute("GetSchool", school);

CreatedAtRoute方法以一個路徑名作爲第一個參數。我懷疑你有一條名爲GetSchool的路線。這是相同控制器中的一個操作名稱。而且CreatedAtRoute不會爲未知路由拋出異常,它只會返回500個錯誤碼。

要解決此問題,使用CreatedAtAction方法,而不是CreatedAtRoute

var route = CreatedAtAction("GetSchool", school); 
板凳
0
0

我認爲這個問題是從API的結果是失敗的序列化。嘗試在單元測試中手動序列化結果並查看失敗的位置。

0
votes
answers
9 views
+10

如何殺死由cmd.exe啓動的進程

2

我試圖停止由c#中的cmd.exe啓動的進程。例如,開始記事本; cmd.exe/c記事本。如何殺死由cmd.exe啓動的進程

System.Diagnostics.ProcessStartInfo("cmd.exe", "/c notepad"); 

當我殺死進程cmd.exe停止。但記事本仍然存在。我如何獲得記事本的句柄並停止它?

+0

你需要殺死'notepad.exe'過程中從'cmd.exe'過程分開。如果您手動執行此操作,您將看到相同的行爲。 – 2012-02-16 22:07:17

沙发
0
7

您應該使用一個自定義的方法,列出了在cmd父進程的所有進程

您需要首先添加System.Management參考。

然後簡單地殺死進程樹:

  void Main() 
      { 

       var psi = new ProcessStartInfo("cmd.exe", "/c notepad"); 
       var cmdProcess = Process.Start(psi); 
       Thread.Sleep(2000); 
       KillProcessAndChildren(cmdProcess.Id); 

      } 

      public void KillProcessAndChildren(int pid) 
      { 
      using (var searcher = new ManagementObjectSearcher 
       ("Select * From Win32_Process Where ParentProcessID=" + pid)) 
      { 
       var moc = searcher.Get(); 
       foreach (ManagementObject mo in moc) 
       { 
        KillProcessAndChildren(Convert.ToInt32(mo["ProcessID"])); 
       } 
       try 
       { 
        var proc = Process.GetProcessById(pid); 
        proc.Kill(); 
       } 
       catch (Exception e) 
       { 
        // Process already exited. 
       } 
      } 
      } 
板凳
0
0

您是否考慮直接開始notepad.exe而不是使用cmd.exe

+0

我需要從命令行啓動我的程序。記事本只是一個例子。 – syloc 2012-02-17 05:54:04

地板
0
0

那麼從命令行您可以使用

的taskkill/MI的cmd.exe/T

0
votes
answers
9 views
+10

保持html頁面內svg的大小

1

我的任務是製作一個程序,該程序將使用輸入數據所要求的數字生成一個PDF文件。在這張圖片中,我們可以看到輸入數據的大小,形狀之間的差距,形狀的類型,藍圖的編號。等等,並且低於實際圖表的樣子。保持html頁面內svg的大小

input data above and actual graphics below

這是非常重要的項目,使用矢量圖形,所以我想過使用SVGs因爲他們真的很靈活,這是比較容易編程生成它們。 然後,我正在使用一個.NET庫(Select.HtmltoPdf)將HTML字符串轉換爲PDF,這非常方便,因爲直接在C#中設計PDF是兩腿之間的痛苦。 使用HTML使我可以使用CSS和我比較熟悉的東西。唯一的缺點是我無法直接使用該庫來渲染svgs,我必須先將它們放入一個html文件中。

當我將SVG插入到HTML中,然後使用庫將其呈現爲PDF時,就會出現問題。 如果我直接在說Corel Draw或Adobe Illustrator中打開svg,尺寸會保留,並且所有內容都應該如此。但是,如果我將該文件的擴展名更改爲.html並在Chrome中打開它,然後打印爲PDF或直接從我的程序渲染PDF,則形狀會略微縮小。

我的問題是如何在html頁面中顯示它們時保持路徑的尺寸不變。

這裏是我當前的.svg:

<svg x="0" y="0" width="215.9mm" height="279.4mm" viewBox="0 0 215.9 279.4"> 
<rect x="40" y="40" width="25" height="25" rx="1.5875" ry="1.5875" stroke="black" stroke-width="0.5" fill-opacity="1"/> 
<ellipse cx="20" cy="20" rx="20" ry="20" stroke="black" stroke-width="0.5" fill-opacity="0"/> 
</svg> 

而且我嘗試使用HTML,這是基本相同的SVG與周圍<html>標籤。

<!DOCTYPE html> 
 
<html> 
 
<meta HTTP-EQUIV="Content-Style-Type" CONTENT="text/css" CHARSET="UTF-8"/> 
 
<svg x="0" y="0" width="215.9mm" height="279.4mm" viewBox="0 0 215.9 279.4"> 
 
<rect x="40" y="40" width="25" height="25" rx="1.5875" ry="1.5875" stroke="black" stroke-width="0.5" fill-opacity="1"/> 
 
<ellipse cx="20" cy="20" rx="20" ry="20" stroke="black" stroke-width="0.5" fill-opacity="0"/> 
 
</svg> 
 
</html>

謝謝!

0
votes
answers
9 views
+10

C#模擬Request.Browser.MajorVersion使用RhinoMocks

2

我有在MVC控制器以下代碼:C#模擬Request.Browser.MajorVersion使用RhinoMocks

 var isIe6 = Request.Browser.Type.ToUpper().Contains("IE") && Request.Browser.MajorVersion < 7; 

我需要存根出使用犀牛製品的第二部分。我曾經嘗試這樣做:

HttpRequest.Stub(a => a.Browser).Return(new HttpBrowserCapabilitiesWrapper(new HttpBrowserCapabilities 
     { 
      Capabilities = new Dictionary<string, string> 
      { 
       {"majorversion", "11"}, 
       {"MajorVersion", "11"}, 
       {"browser", "IE"}, 
       {"isMobileDevice","false"} 
      } 
     })); 

上面的代碼在代碼MajorVersion返回0。我也試過這個:

HttpRequest.Stub(a => a.Browser.MajorVersion).Return(11); 

這只是在安裝時引發異常,說瀏覽器需要設置。我也嘗試過與上面的HttpBrowserCapabilitiesWrapper相結合,但它仍然說瀏覽器需要設置。

如何在MVC中存根/模擬出Request.Browser.MajorVersion?

一些測試代碼,如果有人需要它:

private BasketController sut; 
    protected HttpRequestBase HttpRequest; 

    [Test] 
    public void ShowsMajorVersionDoesNotWork() 
    { 
     // Arrange 
     HttpRequest.Stub(a => a.Browser).Return(new HttpBrowserCapabilitiesWrapper(new HttpBrowserCapabilities 
     { 
      Capabilities = new Dictionary<string, string> 
      { 
       {"majorversion", "11"}, 
       {"MajorVersion", "11"}, 
       {"browser", "IE"}, 
       {"isMobileDevice","false"} 
      } 
     })); 
     //HttpRequest.Stub(a => a.Browser.MajorVersion).Return(11); // Throws Exception 
     sut = new BasketController() 
     { 
      Url = new UrlHelper(new RequestContext(HttpContext, new RouteData()), new RouteCollection()) 
     }; 
     sut.ControllerContext = new ControllerContext(HttpContext, new RouteData(), sut); 


     // Act 
     var result = sut.Method(); 

     // Assert 
     Assert.That(result, Is.EqualTo("11")); // Fails, always returns 0 
    } 

下測試方法BasketController:

public string Method() 
    { 
     return Request.Browser.MajorVersion.ToString(); 
    } 
+0

請向我們展示[mcve](即顯示問題的最簡單的單元測試)。 – mjwills

沙发
0
2

您可以創建HttpBrowserCapabilities使用BrowserCapabilitiesFactory(如解釋here),使用IE11 user-agent string,並相似地,您可以使用正確的字符串嘲笑任何其他瀏覽器MajorVersion

public HttpRequestBase GetInterenetExplorer11StubRequest() 
{ 
    return GetBrowserCapabilitiesStub("Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"); 
} 

public HttpRequestBase GetBrowserCapabilitiesStub(string userAgentString) 
{ 
    var browser = new HttpBrowserCapabilities 
    { 
     Capabilities = new Hashtable { { string.Empty, userAgentString } } 
    }; 
    var factory = new BrowserCapabilitiesFactory(); 
    factory.ConfigureBrowserCapabilities(new NameValueCollection(), browser); 
    var request = MockRepository.GenerateStub<HttpRequestBase>(); 
    request.Stub(a => a.Browser).Return(new HttpBrowserCapabilitiesWrapper(browser)); 
    return request; 
} 
+1

我將這個標記爲答案,當它爲我編譯時,最後一行是錯誤的 – johnstaveley

+0

好點!我更新了代碼以創建具有存根瀏覽器屬性的HttpRequest存根 –

0
votes
answers
9 views
+10

WPF與滑塊更改的ScrollViewer尺寸縮放

-1

我現在有以下代碼:WPF與滑塊更改的ScrollViewer尺寸縮放

<ScrollViewer DockPanel.Dock="Top"> 
      <InkCanvas Name="InkCanvasOnImage" Height="203"> 
       <InkCanvas.LayoutTransform> 
        <ScaleTransform ScaleX="{Binding ElementName=ZoomSlider,Path=Value}" ScaleY="{Binding ElementName=ZoomSlider,Path=Value}"></ScaleTransform> 
       </InkCanvas.LayoutTransform> 
      </InkCanvas> 
     </ScrollViewer> 

     <Slider DockPanel.Dock="Top" Name="ZoomSlider" Value="1" Minimum="0.3" Maximum="3" Height="20" /> 

當我調整滑塊,整個的ScrollViewer是變化的大小,且上下在應用移動滑塊。我想要的只是InkCanvas內部放大和縮小的圖像。我是否使用了正確的WPF控件,或者我在某處搞錯了?我的理解是,我正在改變InkCanvas的縮放比例,而不是滑動條的ScrollViewer Dimensions。

沙发
0
1

應用變尺度在圖像,而不是InkCanvas

<ScrollViewer DockPanel.Dock="Top"> 
      <InkCanvas Name="InkCanvasOnImage" Height="203"> 

       <Image Source="AddImageSourceHere"> 
        <Image.LayoutTransform> 
         <ScaleTransform ScaleX="{Binding ElementName=ZoomSlider,Path=Value}" ScaleY="{Binding ElementName=ZoomSlider,Path=Value}"></ScaleTransform> 
        </Image.LayoutTransform> 
       </Image> 

      </InkCanvas> 
     </ScrollViewer> 

     <Slider DockPanel.Dock="Top" Name="ZoomSlider" Value="1" Minimum="0.3" Maximum="3" Height="20" /> 
+0

因此,這使得圖像放大和縮小,但如果我在圖像上畫,那些沒有相對於圖像縮放。 –

0
votes
answers
8 views
+10

如何在另一個線程內啓動線程

0

我正在探索在另一個線程內啓動線程的概念。這是我提出的代碼,這是淡化了目前我正在開發的另一個程序的版本,但是我發現第二級線程沒有成功完成。如何在另一個線程內啓動線程

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Diagnostics; 

namespace ConsoleApplication4 
{ 
    public class SomeClassA 
    { 
     public SomeClassA(string display) 
     { 
      System.Threading.Thread.Sleep(1000); 
      Console.WriteLine(display); 
     } 
    } 

    public class MainSomeClassA 
    { 
     public List<SomeClassA> SomeClassaAList; 
     public List<Thread> ThreadList; 
     public MainSomeClassA() 
     { 
      ThreadList = new List<Thread>(); 
      SomeClassaAList = new List<SomeClassA>(); 
      for (int i = 0; i < 10; i++) 
      { 
       ThreadList.Add(new Thread(() => StartThread("Hello"))); 
      } 
      WaitComplete(); 
     } 
     public void WaitComplete() 
     { 
      bool AllThreadsAlive = true; 
      while (AllThreadsAlive) 
      { 
       AllThreadsAlive = false; 
       foreach (Thread t in ThreadList) 
       { 
        if (t.IsAlive) 
        { 
         AllThreadsAlive = true; 
        } 
       } 
      } 
     } 
     public void StartThread(string display) 
     { 
      SomeClassaAList.Add(new SomeClassA(display)); 
     } 
    } 

    class Program 
    { 
     public static List<MainSomeClassA> MainSomeClassAList = new List<MainSomeClassA>(); 
     static void Main(string[] args) 
     { 

      Stopwatch sw = new Stopwatch(); 
      MainSomeClassAList = new List<MainSomeClassA>(); 
      List<Thread> ThreadList = new List<Thread>(); 
      bool threadsAlive = true; 
      sw.Reset(); 
      sw.Start(); 
      for (int i = 0; i < 10; i++) 
      { 
       Thread t = new Thread(AddToMainClassAList); 
       t.Start(); 
       ThreadList.Add(t); 
      } 
      while (threadsAlive) 
      { 
       threadsAlive = false; 
       foreach (Thread t in ThreadList) 
       { 
        if (t.IsAlive) 
        { 
         threadsAlive = true; 
        } 
       } 
      } 
      sw.Stop(); 
      Console.WriteLine("Elapsed Time: {0}", sw.ElapsedMilliseconds); 
      Console.ReadKey(); 
     } 

     public static void AddToMainClassAList() 
     { 
      MainSomeClassAList.Add(new MainSomeClassA()); 
     } 

    } 
} 

上面的代碼不會打印出「hello」並退出而不創建SomeClassA列表。

沙发
0
1

你的代碼的問題是你永遠不會啓動內部線程。改變你的構造函數是這樣的,它會工作:

public MainSomeClassA() 
{ 
    ThreadList = new List<Thread>(); 
    SomeClassaAList = new List<SomeClassA>(); 
    for (int i = 0; i < 10; i++) 
    { 
     ThreadList.Add(new Thread(() => StartThread("Hello"))); 
     // Start thread here: 
     ThreadList[ThreadList.Count - 1].Start(); 
    } 
    WaitComplete(); 
} 

這麼說,我要指出,你是幸運的程序不會崩潰。您有10個線程同時嘗試修改MainSomeClassAList對象,其中一些線程必然會強制重新分配內部緩衝區。事實上,如果你在最後打印出列表中的Count,你會發現它並不總是10。

爲使代碼真正正確,您需要在AddToMainClassAList()方法中將呼叫添加到Add()。同樣的事情適用於StartThread()方法和SomeClassaAList對象。

最後,您在線程上等待的方法非常差。你應該儘量避免不惜一切代價進行投票。在這種情況下,Thread.Join()方法是一個合理的選擇(你應該儘量避免阻塞線程,但對於這個例子來說,這是不可避免的)。例如,您的繁忙循環可以被替換爲:

foreach (Thread thread in ThreadList) 
{ 
    thread.Join(); 
} 
0
votes
answers
8 views
+10

使用BackgroundWorker在C#中併發線程

0

我的C#應用??程序是這樣的,後臺工作人員正在用來等待一些傳輸數據的確認。這裏是一些僞代碼演示我想要做的事:使用BackgroundWorker在C#中併發線程

UI_thread 
{ 
    TransmitData() 
    { 
     // load data for tx 
     // fire off TX background worker 
    } 

    RxSerialData() 
    { 
     // if received data is ack, set ack received flag 
    } 
} 

TX_thread 
{ 
    // transmit data 
    // set ack wait timeout 
    // fire off ACK background worker 
    // wait for ACK background worker to complete 
    // evaluate status of ACK background worker as completed, failed, etc. 
} 

ACK_thread 
{ 
    // wait for ack received flag to be set 
} 

會發生什麼事是,ACK BackgroundWorker的超時,並確認沒有收到。我相當肯定它是由遠程設備傳輸的,因爲該設備根本沒有改變,並且C#應用程序正在傳輸。我從這裏改變了ACK線程(當它工作)...

for(i = 0; (i < waitTimeoutVar) && (!bAckRxd); i++) 
{ 
    System.Threading.Thread.Sleep(1); 
} 

...這個...

DateTime dtThen = DateTime.Now(); 
DateTime dtNow; 
TimeSpan stTime; 

do 
{ 
    dtNow = DateTime.Now(); 
    stTime = dtNow - dtThen; 
} 
while ((stTime.TotalMilliseconds < waitTimeoutVar) && (!bAckRxd)); 

後者產生了非常acurate的等待時間相比前者。但是,我想知道是否刪除睡眠功能會干擾接收串行數據的能力。 C#是否只允許一次運行一個線程,也就是說,我是否必須讓線程在某個時間睡眠以允許其他線程運行?

任何想法或建議,你可能會感激。我正在使用Microsoft Visual C#2008速成版。謝謝。

沙发
0
3

RX線程的「新」版本正在利用100%的處理器時間 - 它只是連續運行,從不休眠。除了這種方法的一般性質外,這個可能(雖然不是肯定)會阻止其他一些事情,比如接收數據,不能及時發生。

對於等待的情況就是這樣,一個通常會使用稱爲事件線程同步結構。您創建一個「事件」對象,並且RX線程在其上等待,而處理線程在接收到ACK時發信號通知事件。

AutoResetEvent event = new AutoResetEvent(false); 

// ... 
// ACK waiting thread: 
event.WaitOne(); 
// ... 

// ... 
// Whatever thread actually receives the ACK 
if (/* ack received */) 
{ 
    // bAckRxd = true; - comment this out. Replace with following: 
    event.Set(); 
} 

至於爲什麼你沒有收到你的ACK,我需要更多的信息。頻道究竟是什麼?它是串口嗎?網絡?管?還有別的嗎?

+0

謝謝,費奧多爾。這似乎是訣竅。我正在使用串行通信。 – 2010-05-11 20:34:34

+0

很高興幫助。別客氣。 :-) – 2010-05-11 22:25:24

板凳
0
3

要回答C#是否允許一次運行一個線程的直接問題,C#與線程無關。但是,.NET框架將允許您一次運行多個(邏輯)線程。實際如何處理是框架和操作系統的一個功能。

至於你的問題,我認爲你有太多的線程在等待狀態開始。發送和接收數據的方法應該有異步調用模型(Begin和End)。因此,您應該通過對Begin的調用來啓動傳輸,然後附加在函數終止時調用的回調函數。

然後,在回調中,您將處理結果並繼續執行下一個異步操作(如有必要)或更新UI。

地板
0
1

你的代碼是相當快樂的。當你希望他們計時時,這確實會讓你陷入麻煩。特別是當您使用BGW或線程池線程時,調度程序只允許它們在沒有更多線程處於活動狀態時運行,而不是CPU核心。或者當線程「卡住」了一段時間。你的卡住了。您似乎也沒有有效地使用它們,輪詢循環會消耗大量不必要的CPU週期。

槓桿SerialPort類的功能,以避免這種情況:

  • 你不需要傳輸線程。串口驅動程序有一個緩衝區,當數據符合緩衝區時,Write()調用會立即返回。從主線程寫入很好。
  • 您不一定需要接收線程。串口已經有一個,它運行DataReceived事件。它可以碰撞您在傳輸數據時啓動的計時器。
  • SerialPort已具有ReadTimeout屬性。您可以在接收線程中使用它來超時Read()調用。

Sleep()不會干擾串行端口,它們的驅動程序使用硬件中斷讀取數據。

+0

是的,我同意。我消除了4個背景工作者中的2個,並實施了由Fyodor建議的AutoResetEvent。我將不得不仔細看看SerialPort類。謝謝。 – 2010-05-11 20:33:46

0
votes
answers
8 views
+10

一次啓動多個任務,然後在完成其中一個任務時啓動另一個任務

1

我有一個運行在從其他站點下載圖像文件的asp.net web api中運行的代碼。一次啓動多個任務,然後在完成其中一個任務時啓動另一個任務

這是我用來下載圖像的代碼。

 foreach (string file in images) 
     { 
      using (WebClient client = new WebClient()) 
      { 
       await client.DownloadFileTaskAsync(file, path + Path.GetFileName(file));      
      } 
     } 

我真正需要做的是立即開始10次下載。 (例如使用Task.Run ...或者其他方式),然後在最初開始的10逐個完成時逐個開始休息。

For EX。

啓動10個任務

等到了10個任務完成一個

1次時完成,啓動另一個任務

當其他1次完成,啓動另一個任務等等

直到下載列表中的所有圖像。

所以我的代碼運行時最多有10周併發下載量(或小於10,如果沒有更多的圖像被下載。)

我使用.NET 4.5.2

你們可以指出我在正確的方向來實現這一目標嗎?

+0

這不是說這回答你的問題,而是看看Hangfire http://hangfire.io/ - 看起來像是你的需求的完美契合 – 2014-10-10 11:19:04

+0

你可能需要啓動10個任務,然後使用Task .WaitAny(taskList)' – artm 2014-10-10 11:22:42

沙发
0
2

您可以使用SemaphoreSlim扼殺異步工作方式:

private readonly SemaphoreSlim _mutex = new SemaphoreSlim(10); 

... 

var downloads = images.Select(file => DownloadAsync(file)); 
await Task.WhenAll(downloads); 

... 

private async Task DownloadAsync(string file) 
{ 
    await _mutex.WaitAsync(); 
    try 
    { 
    using (WebClient client = new WebClient()) 
    { 
     await client.DownloadFileTaskAsync(file, path + Path.GetFileName(file));      
    } 
    } 
    finally 
    { 
    _mutex.Release(); 
    } 
} 

注:

  • 您可能需要調整System.Net.ServicePointManager.DefaultConnectionLimit
  • 您應該避免在ASP.NET上使用Task.Run。請參閱我的recent MSDN article on async ASP.NET瞭解更多詳情。
+0

很好的答案。謝謝 :) – Amila 2014-10-11 17:50:20

板凳
0
0

我有點想大聲這裏,不知道這是否會工作,別人會希望它改善:

private void startFirst10Tasks() 
{ 
    List<Task> tasks = new List<Task>(); 
    //tasks.Add first 10 tasks 
    taskHandler(tasks); 
} 

private void taskHandler(List<Task> tasks) 
{ 
    Task.Factory.ContinueWhenAny(tasks, winner => 
     { 
      getNewTasks(tasks.Except(new List<Task>{winner})); 
     }); 
} 

private void getNewTasks(List<Task> tasks) 
{ 
    tasks.Add(
     Task.Factory.StartNew(() => 
     { 
      //Next DownloadFileTask 
     }) 
    ); 

    taskHandler(tasks); 
} 
0
votes
answers
8 views
+10

替代在mvc .net核心應用程序中啓動線程?

0

我們製造工廠內部有多種儀器,它們以不同的速度將數據插入數據庫內的多個表格。替代在mvc .net核心應用程序中啓動線程?

每條生產線上都有一臺計算機連接到網頁上,操作員輸入分配的作業編號並顯示一些相關信息。

我們的目標是根據工廠設備插入的數據顯示指示。狀態與原材料可用性,倉庫存儲可用性,溫度範圍等有關。

我最初的想法是通過產生一條線來修改當前的MVC應用程序,每條生產線每隔10秒掃描插入的信息,並可能推送數據槽通過signarlR來建議操作員。我讀到MVC應用程序中的起始線程是一種不好的做法,可能會影響IIS管理線程的方式。

我想知道如果不使用單獨的線程,如何在MVC中承載獨立於快速回歸的進程?

謝謝你的時間!

沙发
0
0

是的,開始輪詢線程可能不是這裏最好的方法。我可能會建議的另一種解決方案是將您所謂的工具(即當前正在插入數據)修改爲SignalR客戶端,並在每次插入一些數據時向服務器廣播一條消息。然後SignalR服務器可以簡單地將此消息廣播到與之連接的JavaScript SignalR客戶端。通過這種方式,您可以在生產數據的儀器和可以實時顯示此數據的瀏覽器客戶端之間實現(通過SignalR服務器)的直接通信。

+0

對不起,我會添加更多信息。這些設備使用梯形圖編程的PLC,這是工業和實時的。它確實支持數據庫上的CRUD操作。 –

+0

此外,我想保留服務器上的業務規則計算,因爲我們正在越來越多地將數據集成到其他系統(如ERP)。 –

+0

然後,您可能想要抽象一些您的設備將調用的API背後的CRUD操作,以便您可以輕鬆地通知SignalR服務器關於傳入更新。相信我,你完全不希望在ASP.NET應用程序中產生輪詢線程。這就像想要在腳下開槍一樣。 –

0
votes
answers
8 views
+10

由HardwareButton啓動的Xamarin IntentService

3

我現在試了好幾天才得以運行,沒有任何成功。由HardwareButton啓動的Xamarin IntentService

我試圖通過他們特定的SDK(它是松下Toughpad)的功能從我的掌上電腦的硬件按鈕作出反應。我在Xamarin中生成了這段代碼,並且我在Java中獲得了一個SDK的樣本。

這裏是我的代碼:

首先是服務本身。 服務類:

[Service] 
    [IntentFilter(new[] { "com.panasonic.toughpad.android.api.appbutton.intent.APPBUTTON" })] 
    class ButtonIntentService : IntentService 
    { 
     public ButtonIntentService() :base("ButtonIntentHandlerThread"){ } 

     protected override void OnHandleIntent(Intent intent) 
     { 
      if (!intent.Action.Equals(AppButtonManager.ActionAppbutton)) 
      { 
       return; 
      } 

      if (ButtonTestFragment.getInstance() !=null) 
      { 
       ButtonTestFragment.getInstance().updateButtonState(intent); 
      } 
      else 
      { 

      } 
     } 

這裏的剪斷的AndroidManifest的代碼。 AndroidManifest:

<service 
     android:enabled="true" 
     android:name="com.SoftwareTestXamarin.Droid.ButtonIntentService" 
     android:label="button api Sample" 
     android:exported="true"> 
    <intent-filter> 
    <action android:name="com.panasonic.toughpad.android.api.appbutton.intent.APPBUTTON"/> 
    </intent-filter> 
</service> 

我是新API在連接這些東西。在我的想法中,意圖現在應該通過過濾器在HandheldButtons上聽到。所以當我點擊我的手持設備的AppButton時,它應該啓動IntentServices函數?!?或者我錯了? 在我的意見中,他們在Java示例中也做了同樣的事情。

代碼:

服務類:

public class ButtonIntentService extends IntentService { 

    public ButtonIntentService() { 
     super("Button Intent Handler Thread"); 
    } 

    @Override 
    protected void onHandleIntent(Intent intent) { 
     if (!intent.getAction().equals(AppButtonManager.ACTION_APPBUTTON)) { 
      // Ignore.. 
      return; 
     } 

     if (ButtonTestFragment.getInstance() != null) { 
      ButtonTestFragment.getInstance().updateButtonState(intent); 
     } 

    } 

AndroidManifest:

<service 
      android:name="com.panasonic.toughpad.android.sample.buttons.ButtonIntentService" 
      android:label="@string/lbl_button_service" 
      android:exported="true"> 
      <intent-filter> 
       <action android:name="com.panasonic.toughpad.android.api.appbutton.intent.APPBUTTON"/> 
      </intent-filter> 
     </service> 

---- UPDATE 04.08 ----

只是供你參考。我也嘗試從APPBUTTON得到BroadcastReceiver的事件,並讓它開始IntentService沒有任何成功。以下是所添加的代碼片段:

[BroadcastReceiver] 
    [IntentFilter(new[] { "com.panasonic.toughpad.android.api.appbutton.intent.APPBUTTON" }, Priority = (int)IntentFilterPriority.HighPriority)] 
    class ButtonReceiver : BroadcastReceiver 
    { 
     public override void OnReceive(Context context, Intent intent) 
     { 
      var serviceIntent = new Intent(context, typeof(ButtonIntentService)); 
      serviceIntent.PutExtras(intent); 
      context.StartService(serviceIntent); 
     } 
    } 

片段AndroidManifest的:

<receiver android:name="ButtonReceiver"> 
     <intent-filter> 
      <action android:name="com.panasonic.toughpad.android.api.appbutton.intent.APPBUTTON"/> 
     </intent-filter> 
    </receiver> 
+1

一些事情要檢查,因爲我沒有看到它在你的代碼中:1)Xamarin應用程序中給出的適當權限與示例應用程序相比較嗎? (你能鏈接到示例應用程序嗎?) 2)確保可以播放此自定義意圖,然後正確接收。使用SendBroadcast(意圖)在本地活動中測試。 –

沙发
0
0

我現在得到了一個解決這個問題。

你必須檢查是否有設備按鈕的控制。如果沒有,則必須通過菜單爲按鈕選擇IntentService。選擇你的應用程序後,該服務將起作用。 這個簡單的檢查會在處理與IntentService的問題:

if (!AppButtonManager.HasButtonControl) 
       { 
        Intent reconfigureApp = new Intent(Intent.ActionMain); 
        reconfigureApp.AddCategory(Intent.CategoryLauncher); 
        reconfigureApp.SetFlags(ActivityFlags.NewTask); 
        reconfigureApp.SetComponent(new ComponentName("com.panasonic.toughpad.android.service", 
                   "com.panasonic.toughpad.android.appbuttondelegator.ConfigActivity")); 
        activity.StartActivity(reconfigureApp); 
       } 

你不需要的廣播服務使用這個解決方案。 IntentService本身就足夠了。