Azure Web作业/队列 - DecoderFallbackException

时间:2014-07-23 08:47:29

标签: c# azure azure-webjobs azure-storage-queues

我正在使用Azure Web作业功能。这就是我的所作所为。

第1步

  • 我得到了一个Web Api项目,它总是从同一个客户端应用程序中发现相同的字符串。
  • 我有一个名为SimpleClass的简单类,它只有一个属性,同一个客户端应用程序中的始终是相同的字符串。 (字符串为APA91bELkr6CyBmqLbWomwkI2zw_GkXGVsblYH60l4hERXw9ZkCcXufjJM_7IZXI5_Ry9aze6AhYRVzBfl6CYq0kxrdV4ViPkW5hK2Rd2HlsZCDfhnOc3PGLt_SzIMjfbMRug_eK_di2YbJTA6weczoTyb-dKuvnwg
  • 我使用JsonConvert将其序列化为Json字符串
  • 我将其写入Azure存储队列

第2步

  • 我创建了一个非常简单的Azure Web作业演示作业来处理队列
  • 作业反序列化对象

但我有时会得到一个例外(只有一些时间,这很糟糕)

Unhandled Exception: System.Text.DecoderFallbackException: Unable to translate bytes [FF] at index 4 from specified code page to Unicode.
at System.Text.DecoderExceptionFallbackBuffer.Throw(Byte[] bytesUnknown, Int32 index)
at System.Text.DecoderExceptionFallbackBuffer.Fallback(Byte[] bytesUnknown, Int32 index)
at System.Text.DecoderFallbackBuffer.InternalFallback(Byte[] bytes, Byte* pBytes)
at System.Text.UTF8Encoding.GetCharCount(Byte* bytes, Int32 count, DecoderNLS baseDecoder)
at System.String.CreateStringFromEncoding(Byte* bytes, Int32 byteLength, Encoding encoding)
at System.Text.UTF8Encoding.GetString(Byte[] bytes, Int32 index, Int32 count)
at Microsoft.WindowsAzure.Storage.Queue.CloudQueueMessage.get_AsString()
at Microsoft.Azure.Jobs.QueueCausalityHelper.GetOwner(CloudQueueMessage msg)
at Microsoft.Azure.Jobs.Host.Runners.Worker.GetFunctionInvocation(FunctionDefinition func, RuntimeBindingProviderContext context, CloudQueueMessage msg)
at Microsoft.Azure.Jobs.Host.Runners.Worker.MyInvoker.Microsoft.Azure.Jobs.ITriggerInvoke.OnNewQueueItem(CloudQueueMessage msg, QueueTrigger trigger, RuntimeBindingProviderContext context)
at Microsoft.Azure.Jobs.Host.Triggers.PollQueueCommand.TryExecute()
at Microsoft.Azure.Jobs.LinearSpeedupTimerCommand.Execute()
at Microsoft.Azure.Jobs.IntervalSeparationTimer.RunTimer(Object state)
at System.Threading.TimerQueueTimer.CallCallbackInContext(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.TimerQueueTimer.CallCallback()
at System.Threading.TimerQueueTimer.Fire()
at System.Threading.TimerQueue.FireQueuedTimerCompletion(Object state)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

这是我的代码

Web Api控制器

public class TestController : ApiController
{
    public HttpResponseMessage Post(Model model)
    {
        // Retrieve storage account from connection string.
        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
            CloudConfigurationManager.GetSetting("StorageConnectionString"));

        // Create the queue client.
        CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();

        // Retrieve a reference to a queue.
        CloudQueue queue = queueClient.GetQueueReference("webjobsqueue");

        // Create the queue if it doesn't already exist.
        queue.CreateIfNotExists();

        // Create a message and add it to the queue.
        CloudQueueMessage message = new CloudQueueMessage(JsonConvert.SerializeObject(new SimpleClass { SimpleStringProperty = Model.Value }));
        queue.AddMessage(message);

        return new HttpResponseMessage(HttpStatusCode.OK);
    }
}

网络工作

class Program
{
    static void Main(string[] args)
    {
        var host = new JobHost();
        host.RunAndBlock();
    }

    public static void WaitForMessageInQueue([QueueTrigger("webjobsqueue")]
                                       string message)
    {
        var simpleClass = JsonConvert.DeserializeObject<SimpleClass >(message);
        Console.Out(simpleClass.SimpleStringProperty );
    }
}

MSDN论坛中有一个帖子有同样的问题,但没有解决方案

WebJobs Feedback

2 个答案:

答案 0 :(得分:0)

并非每个字节序列都是有效的UTF-8文本。如果您收到有效的随机Unicode / UTF-8字符串,一切都应该正常工作。但是,如果您正在接收随机字节(不是UTF-8文本),则会出现此行为。 CloudQueueMessage是用于处理队列消息的Azure Storage SDK的API,在将其交回给您之前,它会验证它是否具有有效文本。显然,其他一些类不进行这种验证,而是默默地忽略无效文本。

我建议在Web API操作中验证Model.Value,以确保在将消息添加到队列之前它是有效的Unicode文本。我建议使用model.Value.Normalize()的结果,它表示如果字符串包含无效的Unicode数据,它将抛出。

答案 1 :(得分:0)

我正在使用Webjob SDK的最新版本,使用您的代码,每件事情都可以正常使用:

我创建了一个简单的模型:

public class SimpleClass
{
    public string SimpleStringProperty { get; set; }
}

一个类功能:

public class Function
{
    public void WaitForMessageInQueue([QueueTrigger("webjobsqueue")] string message)
    {
        Console.Out.WriteLine(message);
    }
}

这是我的示例网络工作计划:

class Program
{
    // Please set the following connection strings in app.config for this WebJob to run:
    // AzureWebJobsDashboard and AzureWebJobsStorage
    static void Main()
    {

        // Retrieve storage account from connection string.
        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
            CloudConfigurationManager.GetSetting("MyConnectionString"));

        // Create the queue client.
        CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();

        // Retrieve a reference to a queue.
        CloudQueue queue = queueClient.GetQueueReference("webjobsqueue");

        // Create the queue if it doesn't already exist.
        queue.CreateIfNotExists();

        // Create a message and add it to the queue.
        CloudQueueMessage message = new CloudQueueMessage(JsonConvert.SerializeObject(new SimpleClass { SimpleStringProperty = "APA91bELkr6CyBmqLbWomwkI2zw_GkXGVsblYH60l4hERXw9ZkCcXufjJM_7IZXI5_Ry9aze6AhYRVzBfl6CYq0kxrdV4ViPkW5hK2Rd2HlsZCDfhnOc3PGLt_SzIMjfbMRug_eK_di2YbJTA6weczoTyb-dKuvnwg" }));
        queue.AddMessage(message);

        var host = new JobHost();
        host.RunAndBlock();
    }
}